mirror of
https://github.com/firefly-iii/firefly-iii.git
synced 2026-01-10 16:14:10 +00:00
Compare commits
14 Commits
develop-20
...
develop-20
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9c195dcc66 | ||
|
|
0b45506e52 | ||
|
|
51e58f8d88 | ||
|
|
d0c658e79a | ||
|
|
35e0791a9f | ||
|
|
637ecc66d2 | ||
|
|
3a38175b2a | ||
|
|
d78fd86d7a | ||
|
|
395332d6dd | ||
|
|
c5cbceb81a | ||
|
|
ec94f1bcf1 | ||
|
|
ee3d18a8ea | ||
|
|
a9cd8b6512 | ||
|
|
5bd87036b0 |
@@ -34,7 +34,6 @@ use FireflyIII\Support\JsonApi\Enrichments\TransactionGroupEnrichment;
|
|||||||
use FireflyIII\Transformers\TransactionGroupTransformer;
|
use FireflyIII\Transformers\TransactionGroupTransformer;
|
||||||
use FireflyIII\User;
|
use FireflyIII\User;
|
||||||
use Illuminate\Http\JsonResponse;
|
use Illuminate\Http\JsonResponse;
|
||||||
use Illuminate\Support\Facades\Log;
|
|
||||||
use League\Fractal\Resource\Item;
|
use League\Fractal\Resource\Item;
|
||||||
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
||||||
|
|
||||||
@@ -73,26 +72,24 @@ class UpdateController extends Controller
|
|||||||
public function update(UpdateRequest $request, TransactionGroup $transactionGroup): JsonResponse
|
public function update(UpdateRequest $request, TransactionGroup $transactionGroup): JsonResponse
|
||||||
{
|
{
|
||||||
app('log')->debug('Now in update routine for transaction group');
|
app('log')->debug('Now in update routine for transaction group');
|
||||||
$data = $request->getAll();
|
$data = $request->getAll();
|
||||||
$oldAmount = $this->groupRepository->getTotalAmount($transactionGroup);
|
$oldHash = $this->groupRepository->getCompareHash($transactionGroup);
|
||||||
$transactionGroup = $this->groupRepository->update($transactionGroup, $data);
|
$transactionGroup = $this->groupRepository->update($transactionGroup, $data);
|
||||||
$newAmount = $this->groupRepository->getTotalAmount($transactionGroup);
|
$newHash = $this->groupRepository->getCompareHash($transactionGroup);
|
||||||
$manager = $this->getManager();
|
$manager = $this->getManager();
|
||||||
|
|
||||||
Log::debug(sprintf('Old amount: %s, new amount: %s', $oldAmount, $newAmount));
|
|
||||||
|
|
||||||
app('preferences')->mark();
|
app('preferences')->mark();
|
||||||
$applyRules = $data['apply_rules'] ?? true;
|
$applyRules = $data['apply_rules'] ?? true;
|
||||||
$fireWebhooks = $data['fire_webhooks'] ?? true;
|
$fireWebhooks = $data['fire_webhooks'] ?? true;
|
||||||
$amountChanged = 0 !== bccomp($oldAmount, $newAmount);
|
$runRecalculations = $oldHash !== $newHash;
|
||||||
event(new UpdatedTransactionGroup($transactionGroup, $applyRules, $fireWebhooks, $amountChanged));
|
event(new UpdatedTransactionGroup($transactionGroup, $applyRules, $fireWebhooks, $runRecalculations));
|
||||||
|
|
||||||
/** @var User $admin */
|
/** @var User $admin */
|
||||||
$admin = auth()->user();
|
$admin = auth()->user();
|
||||||
|
|
||||||
// use new group collector:
|
// use new group collector:
|
||||||
/** @var GroupCollectorInterface $collector */
|
/** @var GroupCollectorInterface $collector */
|
||||||
$collector = app(GroupCollectorInterface::class);
|
$collector = app(GroupCollectorInterface::class);
|
||||||
$collector
|
$collector
|
||||||
->setUser($admin)
|
->setUser($admin)
|
||||||
// filter on transaction group.
|
// filter on transaction group.
|
||||||
@@ -101,20 +98,20 @@ class UpdateController extends Controller
|
|||||||
->withAPIInformation()
|
->withAPIInformation()
|
||||||
;
|
;
|
||||||
|
|
||||||
$selectedGroup = $collector->getGroups()->first();
|
$selectedGroup = $collector->getGroups()->first();
|
||||||
if (null === $selectedGroup) {
|
if (null === $selectedGroup) {
|
||||||
throw new NotFoundHttpException();
|
throw new NotFoundHttpException();
|
||||||
}
|
}
|
||||||
|
|
||||||
// enrich
|
// enrich
|
||||||
$enrichment = new TransactionGroupEnrichment();
|
$enrichment = new TransactionGroupEnrichment();
|
||||||
$enrichment->setUser($admin);
|
$enrichment->setUser($admin);
|
||||||
$selectedGroup = $enrichment->enrichSingle($selectedGroup);
|
$selectedGroup = $enrichment->enrichSingle($selectedGroup);
|
||||||
|
|
||||||
/** @var TransactionGroupTransformer $transformer */
|
/** @var TransactionGroupTransformer $transformer */
|
||||||
$transformer = app(TransactionGroupTransformer::class);
|
$transformer = app(TransactionGroupTransformer::class);
|
||||||
$transformer->setParameters($this->parameters);
|
$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);
|
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -65,29 +65,29 @@ class UpdateController extends Controller
|
|||||||
public function update(UpdateRequest $request, TransactionGroup $transactionGroup): JsonResponse
|
public function update(UpdateRequest $request, TransactionGroup $transactionGroup): JsonResponse
|
||||||
{
|
{
|
||||||
app('log')->debug('Now in update routine for transaction group [v2]!');
|
app('log')->debug('Now in update routine for transaction group [v2]!');
|
||||||
$data = $request->getAll();
|
$data = $request->getAll();
|
||||||
$transactionGroup = $this->groupRepository->update($transactionGroup, $data);
|
$transactionGroup = $this->groupRepository->update($transactionGroup, $data);
|
||||||
$applyRules = $data['apply_rules'] ?? true;
|
$applyRules = $data['apply_rules'] ?? true;
|
||||||
$fireWebhooks = $data['fire_webhooks'] ?? true;
|
$fireWebhooks = $data['fire_webhooks'] ?? true;
|
||||||
$amountChanged = true;
|
$runRecalculations = true;
|
||||||
|
|
||||||
event(new UpdatedTransactionGroup($transactionGroup, $applyRules, $fireWebhooks, $amountChanged));
|
event(new UpdatedTransactionGroup($transactionGroup, $applyRules, $fireWebhooks, $runRecalculations));
|
||||||
app('preferences')->mark();
|
app('preferences')->mark();
|
||||||
|
|
||||||
/** @var User $admin */
|
/** @var User $admin */
|
||||||
$admin = auth()->user();
|
$admin = auth()->user();
|
||||||
|
|
||||||
// use new group collector:
|
// use new group collector:
|
||||||
/** @var GroupCollectorInterface $collector */
|
/** @var GroupCollectorInterface $collector */
|
||||||
$collector = app(GroupCollectorInterface::class);
|
$collector = app(GroupCollectorInterface::class);
|
||||||
$collector->setUser($admin)->setTransactionGroup($transactionGroup);
|
$collector->setUser($admin)->setTransactionGroup($transactionGroup);
|
||||||
|
|
||||||
$selectedGroup = $collector->getGroups()->first();
|
$selectedGroup = $collector->getGroups()->first();
|
||||||
if (null === $selectedGroup) {
|
if (null === $selectedGroup) {
|
||||||
throw new FireflyException('200032: Cannot find transaction. Possibly, a rule deleted this transaction after its creation.');
|
throw new FireflyException('200032: Cannot find transaction. Possibly, a rule deleted this transaction after its creation.');
|
||||||
}
|
}
|
||||||
|
|
||||||
$transformer = new TransactionGroupTransformer();
|
$transformer = new TransactionGroupTransformer();
|
||||||
$transformer->setParameters($this->parameters);
|
$transformer->setParameters($this->parameters);
|
||||||
|
|
||||||
return response()->api($this->jsonApiObject('transactions', $selectedGroup, $transformer))->header('Content-Type', self::CONTENT_TYPE);
|
return response()->api($this->jsonApiObject('transactions', $selectedGroup, $transformer))->header('Content-Type', self::CONTENT_TYPE);
|
||||||
|
|||||||
@@ -58,6 +58,7 @@ class CorrectsGroupAccounts extends Command
|
|||||||
$handler = new UpdatedGroupEventHandler();
|
$handler = new UpdatedGroupEventHandler();
|
||||||
foreach ($groups as $groupId) {
|
foreach ($groups as $groupId) {
|
||||||
$group = TransactionGroup::find($groupId);
|
$group = TransactionGroup::find($groupId);
|
||||||
|
// TODO in theory the "unifyAccounts" method could lead to the need for run recalculations.
|
||||||
$event = new UpdatedTransactionGroup($group, true, true, false);
|
$event = new UpdatedTransactionGroup($group, true, true, false);
|
||||||
$handler->unifyAccounts($event);
|
$handler->unifyAccounts($event);
|
||||||
}
|
}
|
||||||
|
|||||||
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.
|
* Create a new event instance.
|
||||||
*/
|
*/
|
||||||
public function __construct(public TransactionGroup $transactionGroup, public bool $applyRules, public bool $fireWebhooks, public bool $amountChanged) {}
|
public function __construct(public TransactionGroup $transactionGroup, public bool $applyRules, public bool $fireWebhooks, public bool $runRecalculations) {}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,6 +24,10 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace FireflyIII\Handlers\Events\Model;
|
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\Models\TransactionGroup;
|
||||||
use FireflyIII\Events\Model\PiggyBank\ChangedAmount;
|
use FireflyIII\Events\Model\PiggyBank\ChangedAmount;
|
||||||
use FireflyIII\Models\PiggyBankEvent;
|
use FireflyIII\Models\PiggyBankEvent;
|
||||||
@@ -33,6 +37,24 @@ use FireflyIII\Models\PiggyBankEvent;
|
|||||||
*/
|
*/
|
||||||
class PiggyBankEventHandler
|
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
|
public function changePiggyAmount(ChangedAmount $event): void
|
||||||
{
|
{
|
||||||
// find journal if group is present.
|
// find journal if group is present.
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ class UpdatedGroupEventHandler
|
|||||||
$this->processRules($event);
|
$this->processRules($event);
|
||||||
$this->recalculateCredit($event);
|
$this->recalculateCredit($event);
|
||||||
$this->triggerWebhooks($event);
|
$this->triggerWebhooks($event);
|
||||||
if ($event->amountChanged) {
|
if ($event->runRecalculations) {
|
||||||
$this->updateRunningBalance($event);
|
$this->updateRunningBalance($event);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -75,13 +75,22 @@ class AmountController extends Controller
|
|||||||
$totalSaved = $this->piggyRepos->getCurrentAmount($piggyBank);
|
$totalSaved = $this->piggyRepos->getCurrentAmount($piggyBank);
|
||||||
foreach ($piggyBank->accounts as $account) {
|
foreach ($piggyBank->accounts as $account) {
|
||||||
$leftOnAccount = $this->piggyRepos->leftOnAccount($piggyBank, $account, $date);
|
$leftOnAccount = $this->piggyRepos->leftOnAccount($piggyBank, $account, $date);
|
||||||
$savedSoFar = $this->piggyRepos->getCurrentAmount($piggyBank, $account);
|
$leftToSave = bcsub($piggyBank->target_amount, $totalSaved);
|
||||||
$leftToSave = bcsub($piggyBank->target_amount, $savedSoFar);
|
|
||||||
$maxAmount = 0 === bccomp($piggyBank->target_amount, '0') ? $leftOnAccount : min($leftOnAccount, $leftToSave);
|
$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[] = [
|
$accounts[] = [
|
||||||
'account' => $account,
|
'account' => $account,
|
||||||
'left_on_account' => $leftOnAccount,
|
'left_on_account' => $leftOnAccount,
|
||||||
'saved_so_far' => $savedSoFar,
|
'total_saved' => $totalSaved,
|
||||||
'left_to_save' => $leftToSave,
|
'left_to_save' => $leftToSave,
|
||||||
'max_amount' => $maxAmount,
|
'max_amount' => $maxAmount,
|
||||||
];
|
];
|
||||||
@@ -100,18 +109,18 @@ class AmountController extends Controller
|
|||||||
public function addMobile(PiggyBank $piggyBank)
|
public function addMobile(PiggyBank $piggyBank)
|
||||||
{
|
{
|
||||||
/** @var Carbon $date */
|
/** @var Carbon $date */
|
||||||
$date = session('end', today(config('app.timezone')));
|
$date = session('end', today(config('app.timezone')));
|
||||||
$accounts = [];
|
$accounts = [];
|
||||||
$total = '0';
|
$total = '0';
|
||||||
|
$totalSaved = $this->piggyRepos->getCurrentAmount($piggyBank);
|
||||||
foreach ($piggyBank->accounts as $account) {
|
foreach ($piggyBank->accounts as $account) {
|
||||||
$leftOnAccount = $this->piggyRepos->leftOnAccount($piggyBank, $account, $date);
|
$leftOnAccount = $this->piggyRepos->leftOnAccount($piggyBank, $account, $date);
|
||||||
$savedSoFar = $this->piggyRepos->getCurrentAmount($piggyBank, $account);
|
$leftToSave = bcsub($piggyBank->target_amount, $totalSaved);
|
||||||
$leftToSave = bcsub($piggyBank->target_amount, $savedSoFar);
|
|
||||||
$maxAmount = 0 === bccomp($piggyBank->target_amount, '0') ? $leftOnAccount : min($leftOnAccount, $leftToSave);
|
$maxAmount = 0 === bccomp($piggyBank->target_amount, '0') ? $leftOnAccount : min($leftOnAccount, $leftToSave);
|
||||||
$accounts[] = [
|
$accounts[] = [
|
||||||
'account' => $account,
|
'account' => $account,
|
||||||
'left_on_account' => $leftOnAccount,
|
'left_on_account' => $leftOnAccount,
|
||||||
'saved_so_far' => $savedSoFar,
|
'total_saved' => $totalSaved,
|
||||||
'left_to_save' => $leftToSave,
|
'left_to_save' => $leftToSave,
|
||||||
'max_amount' => $maxAmount,
|
'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.
|
* Edit a piggy bank.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -292,7 +292,7 @@ class ConvertController extends Controller
|
|||||||
$group->refresh();
|
$group->refresh();
|
||||||
|
|
||||||
session()->flash('success', (string) trans('firefly.converted_to_'.$destinationType->type));
|
session()->flash('success', (string) trans('firefly.converted_to_'.$destinationType->type));
|
||||||
event(new UpdatedTransactionGroup($group, true, true, false));
|
event(new UpdatedTransactionGroup($group, true, true, true));
|
||||||
|
|
||||||
return redirect(route('transactions.show', [$group->id]));
|
return redirect(route('transactions.show', [$group->id]));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -191,15 +191,15 @@ class MassController extends Controller
|
|||||||
*/
|
*/
|
||||||
private function updateJournal(int $journalId, MassEditJournalRequest $request): void
|
private function updateJournal(int $journalId, MassEditJournalRequest $request): void
|
||||||
{
|
{
|
||||||
$journal = $this->repository->find($journalId);
|
$journal = $this->repository->find($journalId);
|
||||||
if (!$journal instanceof TransactionJournal) {
|
if (!$journal instanceof TransactionJournal) {
|
||||||
throw new FireflyException(sprintf('Trying to edit non-existent or deleted journal #%d', $journalId));
|
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.
|
// for each field, call the update service.
|
||||||
$service->setTransactionJournal($journal);
|
$service->setTransactionJournal($journal);
|
||||||
|
|
||||||
$data = [
|
$data = [
|
||||||
'date' => $this->getDateFromRequest($request, $journal->id, 'date'),
|
'date' => $this->getDateFromRequest($request, $journal->id, 'date'),
|
||||||
'description' => $this->getStringFromRequest($request, $journal->id, 'description'),
|
'description' => $this->getStringFromRequest($request, $journal->id, 'description'),
|
||||||
'source_id' => $this->getIntFromRequest($request, $journal->id, 'source_id'),
|
'source_id' => $this->getIntFromRequest($request, $journal->id, 'source_id'),
|
||||||
@@ -217,8 +217,8 @@ class MassController extends Controller
|
|||||||
$service->setData($data);
|
$service->setData($data);
|
||||||
$service->update();
|
$service->update();
|
||||||
// trigger rules
|
// trigger rules
|
||||||
$amountChanged = $service->isAmountChanged();
|
$runRecalculations = $service->isCompareHashChanged();
|
||||||
event(new UpdatedTransactionGroup($journal->transactionGroup, true, true, $amountChanged));
|
event(new UpdatedTransactionGroup($journal->transactionGroup, true, true, $runRecalculations));
|
||||||
}
|
}
|
||||||
|
|
||||||
private function getDateFromRequest(MassEditJournalRequest $request, int $journalId, string $key): ?Carbon
|
private function getDateFromRequest(MassEditJournalRequest $request, int $journalId, string $key): ?Carbon
|
||||||
|
|||||||
@@ -24,7 +24,6 @@ declare(strict_types=1);
|
|||||||
namespace FireflyIII\Http\Requests;
|
namespace FireflyIII\Http\Requests;
|
||||||
|
|
||||||
use Illuminate\Contracts\Validation\Validator;
|
use Illuminate\Contracts\Validation\Validator;
|
||||||
use Carbon\Carbon;
|
|
||||||
use FireflyIII\Support\Request\ChecksLogin;
|
use FireflyIII\Support\Request\ChecksLogin;
|
||||||
use Illuminate\Foundation\Http\FormRequest;
|
use Illuminate\Foundation\Http\FormRequest;
|
||||||
use Illuminate\Support\Facades\Log;
|
use Illuminate\Support\Facades\Log;
|
||||||
@@ -41,15 +40,9 @@ class SelectTransactionsRequest extends FormRequest
|
|||||||
*/
|
*/
|
||||||
public function rules(): array
|
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 [
|
return [
|
||||||
'start' => 'required|date|after:'.$first,
|
'start' => 'required|date|after:1900-01-01|before:2099-12-31|before:end|required_with:end',
|
||||||
'end' => 'required|date|before:'.$today,
|
'end' => 'required|date|after:1900-01-01|before:2099-12-31|after:start|required_with:start',
|
||||||
'accounts' => 'required',
|
'accounts' => 'required',
|
||||||
'accounts.*' => 'required|exists:accounts,id|belongsToUser:accounts',
|
'accounts.*' => 'required|exists:accounts,id|belongsToUser:accounts',
|
||||||
];
|
];
|
||||||
|
|||||||
@@ -67,9 +67,10 @@ class UserFailedLoginAttempt extends Notification
|
|||||||
{
|
{
|
||||||
$settings = ReturnsSettings::getSettings('ntfy', 'user', $notifiable);
|
$settings = ReturnsSettings::getSettings('ntfy', 'user', $notifiable);
|
||||||
$message = new Message();
|
$message = new Message();
|
||||||
|
$ip = Request::ip();
|
||||||
$message->topic($settings['ntfy_topic']);
|
$message->topic($settings['ntfy_topic']);
|
||||||
$message->title((string) trans('email.failed_login_subject'));
|
$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;
|
return $message;
|
||||||
}
|
}
|
||||||
@@ -79,7 +80,9 @@ class UserFailedLoginAttempt extends Notification
|
|||||||
*/
|
*/
|
||||||
public function toPushover(User $notifiable): PushoverMessage
|
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'))
|
->title((string) trans('email.failed_login_subject'))
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
@@ -89,7 +92,8 @@ class UserFailedLoginAttempt extends Notification
|
|||||||
*/
|
*/
|
||||||
public function toSlack(User $notifiable): SlackMessage
|
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);
|
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\Deleted;
|
||||||
use FireflyIII\Events\Model\BudgetLimit\Updated;
|
use FireflyIII\Events\Model\BudgetLimit\Updated;
|
||||||
use FireflyIII\Events\Model\PiggyBank\ChangedAmount;
|
use FireflyIII\Events\Model\PiggyBank\ChangedAmount;
|
||||||
|
use FireflyIII\Events\Model\PiggyBank\ChangedName;
|
||||||
use FireflyIII\Events\Model\Rule\RuleActionFailedOnArray;
|
use FireflyIII\Events\Model\Rule\RuleActionFailedOnArray;
|
||||||
use FireflyIII\Events\Model\Rule\RuleActionFailedOnObject;
|
use FireflyIII\Events\Model\Rule\RuleActionFailedOnObject;
|
||||||
use FireflyIII\Events\NewVersionAvailable;
|
use FireflyIII\Events\NewVersionAvailable;
|
||||||
@@ -210,6 +211,9 @@ class EventServiceProvider extends ServiceProvider
|
|||||||
ChangedAmount::class => [
|
ChangedAmount::class => [
|
||||||
'FireflyIII\Handlers\Events\Model\PiggyBankEventHandler@changePiggyAmount',
|
'FireflyIII\Handlers\Events\Model\PiggyBankEventHandler@changePiggyAmount',
|
||||||
],
|
],
|
||||||
|
ChangedName::class => [
|
||||||
|
'FireflyIII\Handlers\Events\Model\PiggyBankEventHandler@changedPiggyBankName',
|
||||||
|
],
|
||||||
|
|
||||||
// budget related events: CRUD budget limit
|
// budget related events: CRUD budget limit
|
||||||
Created::class => [
|
Created::class => [
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ declare(strict_types=1);
|
|||||||
namespace FireflyIII\Repositories\PiggyBank;
|
namespace FireflyIII\Repositories\PiggyBank;
|
||||||
|
|
||||||
use FireflyIII\Events\Model\PiggyBank\ChangedAmount;
|
use FireflyIII\Events\Model\PiggyBank\ChangedAmount;
|
||||||
|
use FireflyIII\Events\Model\PiggyBank\ChangedName;
|
||||||
use FireflyIII\Exceptions\FireflyException;
|
use FireflyIII\Exceptions\FireflyException;
|
||||||
use FireflyIII\Factory\PiggyBankFactory;
|
use FireflyIII\Factory\PiggyBankFactory;
|
||||||
use FireflyIII\Models\Account;
|
use FireflyIII\Models\Account;
|
||||||
@@ -66,7 +67,7 @@ trait ModifiesPiggyBanks
|
|||||||
{
|
{
|
||||||
$currentAmount = $this->getCurrentAmount($piggyBank, $account);
|
$currentAmount = $this->getCurrentAmount($piggyBank, $account);
|
||||||
$pivot = $piggyBank->accounts()->where('accounts.id', $account->id)->first()->pivot;
|
$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;
|
$pivot->native_current_amount = null;
|
||||||
|
|
||||||
// also update native_current_amount.
|
// also update native_current_amount.
|
||||||
@@ -89,7 +90,7 @@ trait ModifiesPiggyBanks
|
|||||||
{
|
{
|
||||||
$currentAmount = $this->getCurrentAmount($piggyBank, $account);
|
$currentAmount = $this->getCurrentAmount($piggyBank, $account);
|
||||||
$pivot = $piggyBank->accounts()->where('accounts.id', $account->id)->first()->pivot;
|
$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;
|
$pivot->native_current_amount = null;
|
||||||
|
|
||||||
// also update native_current_amount.
|
// also update native_current_amount.
|
||||||
@@ -121,13 +122,13 @@ trait ModifiesPiggyBanks
|
|||||||
|
|
||||||
|
|
||||||
if (0 !== bccomp($piggyBank->target_amount, '0')) {
|
if (0 !== bccomp($piggyBank->target_amount, '0')) {
|
||||||
$leftToSave = bcsub($piggyBank->target_amount, (string) $savedSoFar);
|
$leftToSave = bcsub($piggyBank->target_amount, (string)$savedSoFar);
|
||||||
$maxAmount = 1 === bccomp((string) $leftOnAccount, $leftToSave) ? $leftToSave : $leftOnAccount;
|
$maxAmount = 1 === bccomp((string)$leftOnAccount, $leftToSave) ? $leftToSave : $leftOnAccount;
|
||||||
Log::debug(sprintf('Left to save: %s', $leftToSave));
|
Log::debug(sprintf('Left to save: %s', $leftToSave));
|
||||||
Log::debug(sprintf('Maximum amount: %s', $maxAmount));
|
Log::debug(sprintf('Maximum amount: %s', $maxAmount));
|
||||||
}
|
}
|
||||||
|
|
||||||
$compare = bccomp($amount, (string) $maxAmount);
|
$compare = bccomp($amount, (string)$maxAmount);
|
||||||
$result = $compare <= 0;
|
$result = $compare <= 0;
|
||||||
|
|
||||||
Log::debug(sprintf('Compare <= 0? %d, so canAddAmount is %s', $compare, var_export($result, true)));
|
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);
|
$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')) {
|
if (1 === bccomp($amount, $max) && 0 !== bccomp($piggyBank->target_amount, '0')) {
|
||||||
$amount = $max;
|
$amount = $max;
|
||||||
}
|
}
|
||||||
$difference = bcsub($amount, (string) $repetition->current_amount);
|
$difference = bcsub($amount, (string)$repetition->current_amount);
|
||||||
$repetition->current_amount = $amount;
|
$repetition->current_amount = $amount;
|
||||||
$repetition->save();
|
$repetition->save();
|
||||||
|
|
||||||
@@ -211,12 +212,12 @@ trait ModifiesPiggyBanks
|
|||||||
{
|
{
|
||||||
$piggyBank = $this->updateProperties($piggyBank, $data);
|
$piggyBank = $this->updateProperties($piggyBank, $data);
|
||||||
if (array_key_exists('notes', $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:
|
// update the order of the piggy bank:
|
||||||
$oldOrder = $piggyBank->order;
|
$oldOrder = $piggyBank->order;
|
||||||
$newOrder = (int) ($data['order'] ?? $oldOrder);
|
$newOrder = (int)($data['order'] ?? $oldOrder);
|
||||||
if ($oldOrder !== $newOrder) {
|
if ($oldOrder !== $newOrder) {
|
||||||
$this->setOrder($piggyBank, $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,
|
// 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.
|
// remove money from all accounts until the piggy bank is the right amount.
|
||||||
$currentAmount = $this->getCurrentAmount($piggyBank);
|
$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));
|
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:
|
// an amount will be removed, create "negative" event:
|
||||||
// Log::debug(sprintf('ChangedAmount: is triggered with difference "%s"', $difference));
|
// Log::debug(sprintf('ChangedAmount: is triggered with difference "%s"', $difference));
|
||||||
@@ -248,7 +249,7 @@ trait ModifiesPiggyBanks
|
|||||||
|
|
||||||
// update using name:
|
// update using name:
|
||||||
if (array_key_exists('object_group_title', $data)) {
|
if (array_key_exists('object_group_title', $data)) {
|
||||||
$objectGroupTitle = (string) $data['object_group_title'];
|
$objectGroupTitle = (string)$data['object_group_title'];
|
||||||
if ('' !== $objectGroupTitle) {
|
if ('' !== $objectGroupTitle) {
|
||||||
$objectGroup = $this->findOrCreateObjectGroup($objectGroupTitle);
|
$objectGroup = $this->findOrCreateObjectGroup($objectGroupTitle);
|
||||||
if (null !== $objectGroup) {
|
if (null !== $objectGroup) {
|
||||||
@@ -264,7 +265,7 @@ trait ModifiesPiggyBanks
|
|||||||
|
|
||||||
// try also with ID:
|
// try also with ID:
|
||||||
if (array_key_exists('object_group_id', $data)) {
|
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) {
|
if (0 !== $objectGroupId) {
|
||||||
$objectGroup = $this->findObjectGroupById($objectGroupId);
|
$objectGroup = $this->findObjectGroupById($objectGroupId);
|
||||||
if (null !== $objectGroup) {
|
if (null !== $objectGroup) {
|
||||||
@@ -282,6 +283,7 @@ trait ModifiesPiggyBanks
|
|||||||
private function updateProperties(PiggyBank $piggyBank, array $data): PiggyBank
|
private function updateProperties(PiggyBank $piggyBank, array $data): PiggyBank
|
||||||
{
|
{
|
||||||
if (array_key_exists('name', $data) && '' !== $data['name']) {
|
if (array_key_exists('name', $data) && '' !== $data['name']) {
|
||||||
|
event(new ChangedName($piggyBank, $piggyBank->name, $data['name']));
|
||||||
$piggyBank->name = $data['name'];
|
$piggyBank->name = $data['name'];
|
||||||
}
|
}
|
||||||
if (array_key_exists('transaction_currency_id', $data) && is_int($data['transaction_currency_id'])) {
|
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) {
|
foreach ($piggyBank->accounts as $account) {
|
||||||
$current = $account->pivot->current_amount;
|
$current = $account->pivot->current_amount;
|
||||||
// if this account contains more than the amount, remove the amount and return.
|
// 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);
|
$this->removeAmount($piggyBank, $account, $amount);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// if this account contains less than the amount, remove the current amount, update the amount and continue.
|
// if this account contains less than the amount, remove the current amount, update the amount and continue.
|
||||||
$this->removeAmount($piggyBank, $account, $current);
|
$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;
|
namespace FireflyIII\Repositories\PiggyBank;
|
||||||
|
|
||||||
|
use FireflyIII\Events\Model\PiggyBank\ChangedAmount;
|
||||||
use FireflyIII\User;
|
use FireflyIII\User;
|
||||||
use Carbon\Carbon;
|
use Carbon\Carbon;
|
||||||
use FireflyIII\Exceptions\FireflyException;
|
use FireflyIII\Exceptions\FireflyException;
|
||||||
@@ -438,4 +439,14 @@ class PiggyBankRepository implements PiggyBankRepositoryInterface, UserGroupInte
|
|||||||
|
|
||||||
return $search->take($limit)->get(['piggy_banks.*']);
|
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', $account->pivot->current_amount)) {
|
||||||
|
event(new ChangedAmount($piggyBank, $account->pivot->current_amount, null, null));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -47,6 +47,8 @@ use Illuminate\Support\Collection;
|
|||||||
*/
|
*/
|
||||||
interface PiggyBankRepositoryInterface
|
interface PiggyBankRepositoryInterface
|
||||||
{
|
{
|
||||||
|
public function resetHistory(PiggyBank $piggyBank): void;
|
||||||
|
|
||||||
public function addAmount(PiggyBank $piggyBank, Account $account, string $amount, ?TransactionJournal $journal = null): bool;
|
public function addAmount(PiggyBank $piggyBank, Account $account, string $amount, ?TransactionJournal $journal = null): bool;
|
||||||
|
|
||||||
public function addAmountToPiggyBank(PiggyBank $piggyBank, string $amount, TransactionJournal $journal): void;
|
public function addAmountToPiggyBank(PiggyBank $piggyBank, string $amount, TransactionJournal $journal): void;
|
||||||
|
|||||||
@@ -217,7 +217,7 @@ class TransactionGroupRepository implements TransactionGroupRepositoryInterface,
|
|||||||
'link' => $entry->outward,
|
'link' => $entry->outward,
|
||||||
'group' => $entry->destination->transaction_group_id,
|
'group' => $entry->destination->transaction_group_id,
|
||||||
'description' => $entry->destination->description,
|
'description' => $entry->destination->description,
|
||||||
'editable' => 1 === (int) $entry->editable,
|
'editable' => 1 === (int)$entry->editable,
|
||||||
'amount' => $amount,
|
'amount' => $amount,
|
||||||
'foreign_amount' => $foreignAmount,
|
'foreign_amount' => $foreignAmount,
|
||||||
];
|
];
|
||||||
@@ -230,7 +230,7 @@ class TransactionGroupRepository implements TransactionGroupRepositoryInterface,
|
|||||||
'link' => $entry->inward,
|
'link' => $entry->inward,
|
||||||
'group' => $entry->source->transaction_group_id,
|
'group' => $entry->source->transaction_group_id,
|
||||||
'description' => $entry->source->description,
|
'description' => $entry->source->description,
|
||||||
'editable' => 1 === (int) $entry->editable,
|
'editable' => 1 === (int)$entry->editable,
|
||||||
'amount' => $amount,
|
'amount' => $amount,
|
||||||
'foreign_amount' => $foreignAmount,
|
'foreign_amount' => $foreignAmount,
|
||||||
];
|
];
|
||||||
@@ -264,7 +264,7 @@ class TransactionGroupRepository implements TransactionGroupRepositoryInterface,
|
|||||||
if (null === $transaction->foreign_amount || '' === $transaction->foreign_amount) {
|
if (null === $transaction->foreign_amount || '' === $transaction->foreign_amount) {
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
if (0 === bccomp('0', (string) $transaction->foreign_amount)) {
|
if (0 === bccomp('0', (string)$transaction->foreign_amount)) {
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
$currency = $transaction->foreignCurrency;
|
$currency = $transaction->foreignCurrency;
|
||||||
@@ -305,7 +305,7 @@ class TransactionGroupRepository implements TransactionGroupRepositoryInterface,
|
|||||||
$return = [];
|
$return = [];
|
||||||
|
|
||||||
foreach ($query as $row) {
|
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);
|
return new NullArrayObject($return);
|
||||||
@@ -325,7 +325,7 @@ class TransactionGroupRepository implements TransactionGroupRepositoryInterface,
|
|||||||
$return = [];
|
$return = [];
|
||||||
|
|
||||||
foreach ($query as $row) {
|
foreach ($query as $row) {
|
||||||
$return[$row->name] = json_decode((string) $row->data);
|
$return[$row->name] = json_decode((string)$row->data);
|
||||||
}
|
}
|
||||||
|
|
||||||
return new NullArrayObject($return);
|
return new NullArrayObject($return);
|
||||||
@@ -433,20 +433,22 @@ class TransactionGroupRepository implements TransactionGroupRepositoryInterface,
|
|||||||
return $service->update($transactionGroup, $data);
|
return $service->update($transactionGroup, $data);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getTotalAmount(TransactionGroup $group): string
|
public function getCompareHash(TransactionGroup $group): string
|
||||||
{
|
{
|
||||||
$sum = '0';
|
$sum = '0';
|
||||||
|
$names = '';
|
||||||
|
|
||||||
/** @var TransactionJournal $journal */
|
/** @var TransactionJournal $journal */
|
||||||
foreach ($group->transactionJournals as $journal) {
|
foreach ($group->transactionJournals as $journal) {
|
||||||
/** @var Transaction $transaction */
|
/** @var Transaction $transaction */
|
||||||
foreach ($journal->transactions as $transaction) {
|
foreach ($journal->transactions as $transaction) {
|
||||||
if (-1 === bccomp('0', (string) $transaction->amount)) {
|
if (-1 === bccomp('0', (string)$transaction->amount)) {
|
||||||
$sum = bcadd($sum, $transaction->amount);
|
$sum = bcadd($sum, $transaction->amount);
|
||||||
|
$names = sprintf('%s%s', $names, $transaction->account->name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return $sum;
|
return hash('sha256', sprintf('%s-%s', $names, $sum));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -49,7 +49,10 @@ interface TransactionGroupRepositoryInterface
|
|||||||
{
|
{
|
||||||
public function countAttachments(int $journalId): int;
|
public function countAttachments(int $journalId): int;
|
||||||
|
|
||||||
public function getTotalAmount(TransactionGroup $group): string;
|
/**
|
||||||
|
* 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;
|
public function destroy(TransactionGroup $group): void;
|
||||||
|
|
||||||
|
|||||||
@@ -43,6 +43,7 @@ use FireflyIII\Repositories\Bill\BillRepositoryInterface;
|
|||||||
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
|
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
|
||||||
use FireflyIII\Repositories\Category\CategoryRepositoryInterface;
|
use FireflyIII\Repositories\Category\CategoryRepositoryInterface;
|
||||||
use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface;
|
use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface;
|
||||||
|
use FireflyIII\Repositories\TransactionGroup\TransactionGroupRepositoryInterface;
|
||||||
use FireflyIII\Services\Internal\Support\JournalServiceTrait;
|
use FireflyIII\Services\Internal\Support\JournalServiceTrait;
|
||||||
use FireflyIII\Support\Facades\FireflyConfig;
|
use FireflyIII\Support\Facades\FireflyConfig;
|
||||||
use FireflyIII\Support\NullArrayObject;
|
use FireflyIII\Support\NullArrayObject;
|
||||||
@@ -60,6 +61,7 @@ class JournalUpdateService
|
|||||||
|
|
||||||
private BillRepositoryInterface $billRepository;
|
private BillRepositoryInterface $billRepository;
|
||||||
private CurrencyRepositoryInterface $currencyRepository;
|
private CurrencyRepositoryInterface $currencyRepository;
|
||||||
|
private TransactionGroupRepositoryInterface $transactionGroupRepository;
|
||||||
private array $data;
|
private array $data;
|
||||||
private ?Account $destinationAccount;
|
private ?Account $destinationAccount;
|
||||||
private ?Transaction $destinationTransaction;
|
private ?Transaction $destinationTransaction;
|
||||||
@@ -69,26 +71,27 @@ class JournalUpdateService
|
|||||||
private ?Transaction $sourceTransaction;
|
private ?Transaction $sourceTransaction;
|
||||||
private ?TransactionGroup $transactionGroup;
|
private ?TransactionGroup $transactionGroup;
|
||||||
private ?TransactionJournal $transactionJournal;
|
private ?TransactionJournal $transactionJournal;
|
||||||
private bool $amountChanged = false;
|
private string $startCompareHash = '';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* JournalUpdateService constructor.
|
* JournalUpdateService constructor.
|
||||||
*/
|
*/
|
||||||
public function __construct()
|
public function __construct()
|
||||||
{
|
{
|
||||||
$this->destinationAccount = null;
|
$this->destinationAccount = null;
|
||||||
$this->destinationTransaction = null;
|
$this->destinationTransaction = null;
|
||||||
$this->sourceAccount = null;
|
$this->sourceAccount = null;
|
||||||
$this->sourceTransaction = null;
|
$this->sourceTransaction = null;
|
||||||
$this->transactionGroup = null;
|
$this->transactionGroup = null;
|
||||||
$this->transactionJournal = null;
|
$this->transactionJournal = null;
|
||||||
$this->billRepository = app(BillRepositoryInterface::class);
|
$this->billRepository = app(BillRepositoryInterface::class);
|
||||||
$this->categoryRepository = app(CategoryRepositoryInterface::class);
|
$this->categoryRepository = app(CategoryRepositoryInterface::class);
|
||||||
$this->budgetRepository = app(BudgetRepositoryInterface::class);
|
$this->budgetRepository = app(BudgetRepositoryInterface::class);
|
||||||
$this->tagFactory = app(TagFactory::class);
|
$this->tagFactory = app(TagFactory::class);
|
||||||
$this->accountRepository = app(AccountRepositoryInterface::class);
|
$this->accountRepository = app(AccountRepositoryInterface::class);
|
||||||
$this->currencyRepository = app(CurrencyRepositoryInterface::class);
|
$this->currencyRepository = app(CurrencyRepositoryInterface::class);
|
||||||
$this->metaString = [
|
$this->transactionGroupRepository = app(TransactionGroupRepositoryInterface::class);
|
||||||
|
$this->metaString = [
|
||||||
'sepa_cc',
|
'sepa_cc',
|
||||||
'sepa_ct_op',
|
'sepa_ct_op',
|
||||||
'sepa_ct_id',
|
'sepa_ct_id',
|
||||||
@@ -103,7 +106,7 @@ class JournalUpdateService
|
|||||||
'external_id',
|
'external_id',
|
||||||
'external_url',
|
'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', ];
|
'invoice_date', ];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -120,10 +123,12 @@ class JournalUpdateService
|
|||||||
$this->budgetRepository->setUser($transactionGroup->user);
|
$this->budgetRepository->setUser($transactionGroup->user);
|
||||||
$this->tagFactory->setUser($transactionGroup->user);
|
$this->tagFactory->setUser($transactionGroup->user);
|
||||||
$this->accountRepository->setUser($transactionGroup->user);
|
$this->accountRepository->setUser($transactionGroup->user);
|
||||||
|
$this->transactionGroupRepository->setUser($transactionGroup->user);
|
||||||
$this->destinationAccount = null;
|
$this->destinationAccount = null;
|
||||||
$this->destinationTransaction = null;
|
$this->destinationTransaction = null;
|
||||||
$this->sourceAccount = null;
|
$this->sourceAccount = null;
|
||||||
$this->sourceTransaction = null;
|
$this->sourceTransaction = null;
|
||||||
|
$this->startCompareHash = $this->transactionGroupRepository->getCompareHash($transactionGroup);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function setTransactionJournal(TransactionJournal $transactionJournal): void
|
public function setTransactionJournal(TransactionJournal $transactionJournal): void
|
||||||
@@ -675,7 +680,6 @@ class JournalUpdateService
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
$origSourceTransaction = $this->getSourceTransaction();
|
$origSourceTransaction = $this->getSourceTransaction();
|
||||||
$this->amountChanged = 0 !== bccomp($origSourceTransaction->amount, app('steam')->negative($amount));
|
|
||||||
$origSourceTransaction->amount = app('steam')->negative($amount);
|
$origSourceTransaction->amount = app('steam')->negative($amount);
|
||||||
$origSourceTransaction->balance_dirty = true;
|
$origSourceTransaction->balance_dirty = true;
|
||||||
$origSourceTransaction->save();
|
$origSourceTransaction->save();
|
||||||
@@ -818,8 +822,13 @@ class JournalUpdateService
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function isAmountChanged(): bool
|
public function isCompareHashChanged(): bool
|
||||||
{
|
{
|
||||||
return $this->amountChanged;
|
Log::debug(sprintf('Now in %s', __METHOD__));
|
||||||
|
$compareHash = $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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -79,12 +79,12 @@ class ExchangeRateConverter
|
|||||||
public function getCurrencyRate(TransactionCurrency $from, TransactionCurrency $to, Carbon $date): string
|
public function getCurrencyRate(TransactionCurrency $from, TransactionCurrency $to, Carbon $date): string
|
||||||
{
|
{
|
||||||
if (false === $this->enabled()) {
|
if (false === $this->enabled()) {
|
||||||
Log::debug('ExchangeRateConverter: disabled, return "1".');
|
// Log::debug('ExchangeRateConverter: disabled, return "1".');
|
||||||
|
|
||||||
return '1';
|
return '1';
|
||||||
}
|
}
|
||||||
if ($from->id === $to->id) {
|
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';
|
return '1';
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
|||||||
use FireflyIII\Repositories\Journal\JournalRepositoryInterface;
|
use FireflyIII\Repositories\Journal\JournalRepositoryInterface;
|
||||||
use FireflyIII\Support\CacheProperties;
|
use FireflyIII\Support\CacheProperties;
|
||||||
use FireflyIII\Support\Debug\Timer;
|
use FireflyIII\Support\Debug\Timer;
|
||||||
|
use Illuminate\Support\Facades\Log;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Trait PeriodOverview.
|
* Trait PeriodOverview.
|
||||||
@@ -77,6 +78,7 @@ trait PeriodOverview
|
|||||||
*/
|
*/
|
||||||
protected function getAccountPeriodOverview(Account $account, Carbon $start, Carbon $end): array
|
protected function getAccountPeriodOverview(Account $account, Carbon $start, Carbon $end): array
|
||||||
{
|
{
|
||||||
|
Log::debug('Now in getAccountPeriodOverview()');
|
||||||
Timer::start('account-period-total');
|
Timer::start('account-period-total');
|
||||||
$this->accountRepository = app(AccountRepositoryInterface::class);
|
$this->accountRepository = app(AccountRepositoryInterface::class);
|
||||||
$range = app('navigation')->getViewRange(true);
|
$range = app('navigation')->getViewRange(true);
|
||||||
@@ -100,6 +102,7 @@ trait PeriodOverview
|
|||||||
$transactions = $this->accountRepository->periodCollection($account, $start, $end);
|
$transactions = $this->accountRepository->periodCollection($account, $start, $end);
|
||||||
|
|
||||||
// loop dates
|
// loop dates
|
||||||
|
Log::debug(sprintf('Count of loops: %d', count($dates)));
|
||||||
foreach ($dates as $currentDate) {
|
foreach ($dates as $currentDate) {
|
||||||
$title = app('navigation')->periodShow($currentDate['start'], $currentDate['period']);
|
$title = app('navigation')->periodShow($currentDate['start'], $currentDate['period']);
|
||||||
[$transactions, $spent] = $this->filterTransactionsByType(TransactionTypeEnum::WITHDRAWAL, $transactions, $currentDate['start'], $currentDate['end']);
|
[$transactions, $spent] = $this->filterTransactionsByType(TransactionTypeEnum::WITHDRAWAL, $transactions, $currentDate['start'], $currentDate['end']);
|
||||||
@@ -119,6 +122,7 @@ trait PeriodOverview
|
|||||||
}
|
}
|
||||||
$cache->store($entries);
|
$cache->store($entries);
|
||||||
Timer::stop('account-period-total');
|
Timer::stop('account-period-total');
|
||||||
|
Log::debug('End of getAccountPeriodOverview()');
|
||||||
|
|
||||||
return $entries;
|
return $entries;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -67,6 +67,16 @@ class UpdatePiggyBank implements ActionInterface
|
|||||||
|
|
||||||
Log::debug(sprintf('Found piggy bank #%d ("%s")', $piggyBank->id, $piggyBank->name));
|
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 */
|
/** @var Transaction $destination */
|
||||||
$destination = $journalObj->transactions()->where('amount', '>', 0)->first();
|
$destination = $journalObj->transactions()->where('amount', '>', 0)->first();
|
||||||
|
|
||||||
@@ -231,4 +241,9 @@ class UpdatePiggyBank implements ActionInterface
|
|||||||
|
|
||||||
$repository->addAmount($piggyBank, $account, $amount, $journal);
|
$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();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
77
composer.lock
generated
77
composer.lock
generated
@@ -129,16 +129,16 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "brick/math",
|
"name": "brick/math",
|
||||||
"version": "0.12.3",
|
"version": "0.13.1",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/brick/math.git",
|
"url": "https://github.com/brick/math.git",
|
||||||
"reference": "866551da34e9a618e64a819ee1e01c20d8a588ba"
|
"reference": "fc7ed316430118cc7836bf45faff18d5dfc8de04"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/brick/math/zipball/866551da34e9a618e64a819ee1e01c20d8a588ba",
|
"url": "https://api.github.com/repos/brick/math/zipball/fc7ed316430118cc7836bf45faff18d5dfc8de04",
|
||||||
"reference": "866551da34e9a618e64a819ee1e01c20d8a588ba",
|
"reference": "fc7ed316430118cc7836bf45faff18d5dfc8de04",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
@@ -177,7 +177,7 @@
|
|||||||
],
|
],
|
||||||
"support": {
|
"support": {
|
||||||
"issues": "https://github.com/brick/math/issues",
|
"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": [
|
"funding": [
|
||||||
{
|
{
|
||||||
@@ -185,7 +185,7 @@
|
|||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"time": "2025-02-28T13:11:00+00:00"
|
"time": "2025-03-29T13:50:30+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "carbonphp/carbon-doctrine-types",
|
"name": "carbonphp/carbon-doctrine-types",
|
||||||
@@ -939,16 +939,16 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "filp/whoops",
|
"name": "filp/whoops",
|
||||||
"version": "2.18.0",
|
"version": "2.18.1",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/filp/whoops.git",
|
"url": "https://github.com/filp/whoops.git",
|
||||||
"reference": "a7de6c3c6c3c022f5cfc337f8ede6a14460cf77e"
|
"reference": "8fcc6a862f2e7b94eb4221fd0819ddba3d30ab26"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/filp/whoops/zipball/a7de6c3c6c3c022f5cfc337f8ede6a14460cf77e",
|
"url": "https://api.github.com/repos/filp/whoops/zipball/8fcc6a862f2e7b94eb4221fd0819ddba3d30ab26",
|
||||||
"reference": "a7de6c3c6c3c022f5cfc337f8ede6a14460cf77e",
|
"reference": "8fcc6a862f2e7b94eb4221fd0819ddba3d30ab26",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
@@ -998,7 +998,7 @@
|
|||||||
],
|
],
|
||||||
"support": {
|
"support": {
|
||||||
"issues": "https://github.com/filp/whoops/issues",
|
"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.1"
|
||||||
},
|
},
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
@@ -1006,7 +1006,7 @@
|
|||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"time": "2025-03-15T12:00:00+00:00"
|
"time": "2025-06-03T18:56:14+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "firebase/php-jwt",
|
"name": "firebase/php-jwt",
|
||||||
@@ -1879,20 +1879,20 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "laravel/framework",
|
"name": "laravel/framework",
|
||||||
"version": "v12.16.0",
|
"version": "v12.17.0",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/laravel/framework.git",
|
"url": "https://github.com/laravel/framework.git",
|
||||||
"reference": "293bb1c70224faebfd3d4328e201c37115da055f"
|
"reference": "8729d084510480fdeec9b6ad198180147d4a7f06"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/laravel/framework/zipball/293bb1c70224faebfd3d4328e201c37115da055f",
|
"url": "https://api.github.com/repos/laravel/framework/zipball/8729d084510480fdeec9b6ad198180147d4a7f06",
|
||||||
"reference": "293bb1c70224faebfd3d4328e201c37115da055f",
|
"reference": "8729d084510480fdeec9b6ad198180147d4a7f06",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
"brick/math": "^0.11|^0.12",
|
"brick/math": "^0.11|^0.12|^0.13",
|
||||||
"composer-runtime-api": "^2.2",
|
"composer-runtime-api": "^2.2",
|
||||||
"doctrine/inflector": "^2.0.5",
|
"doctrine/inflector": "^2.0.5",
|
||||||
"dragonmantank/cron-expression": "^3.4",
|
"dragonmantank/cron-expression": "^3.4",
|
||||||
@@ -2090,7 +2090,7 @@
|
|||||||
"issues": "https://github.com/laravel/framework/issues",
|
"issues": "https://github.com/laravel/framework/issues",
|
||||||
"source": "https://github.com/laravel/framework"
|
"source": "https://github.com/laravel/framework"
|
||||||
},
|
},
|
||||||
"time": "2025-05-27T15:49:44+00:00"
|
"time": "2025-06-03T14:04:18+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "laravel/passport",
|
"name": "laravel/passport",
|
||||||
@@ -3473,22 +3473,22 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "mailersend/laravel-driver",
|
"name": "mailersend/laravel-driver",
|
||||||
"version": "v2.9.1",
|
"version": "v2.11.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": "63acebb5064745076df27b1a80423986b6d7b69e"
|
||||||
},
|
},
|
||||||
"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/63acebb5064745076df27b1a80423986b6d7b69e",
|
||||||
"reference": "87fd5ab76808bbaac9221be0d306baef13e98725",
|
"reference": "63acebb5064745076df27b1a80423986b6d7b69e",
|
||||||
"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.34.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",
|
||||||
@@ -3536,29 +3536,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.11.0"
|
||||||
},
|
},
|
||||||
"time": "2025-04-09T09:33:07+00:00"
|
"time": "2025-06-04T08:47:41+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "mailersend/mailersend",
|
"name": "mailersend/mailersend",
|
||||||
"version": "v0.31.0",
|
"version": "v0.34.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": "1cb8c42e5569e7455b1e0e794dcbf68e3b7898ab"
|
||||||
},
|
},
|
||||||
"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/1cb8c42e5569e7455b1e0e794dcbf68e3b7898ab",
|
||||||
"reference": "513ff83ee768526055ad52987cde401ea7218c67",
|
"reference": "1cb8c42e5569e7455b1e0e794dcbf68e3b7898ab",
|
||||||
"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",
|
||||||
@@ -3603,9 +3602,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.34.0"
|
||||||
},
|
},
|
||||||
"time": "2025-04-03T12:16:11+00:00"
|
"time": "2025-06-04T07:53:52+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "monolog/monolog",
|
"name": "monolog/monolog",
|
||||||
@@ -3880,16 +3879,16 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "nette/utils",
|
"name": "nette/utils",
|
||||||
"version": "v4.0.6",
|
"version": "v4.0.7",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/nette/utils.git",
|
"url": "https://github.com/nette/utils.git",
|
||||||
"reference": "ce708655043c7050eb050df361c5e313cf708309"
|
"reference": "e67c4061eb40b9c113b218214e42cb5a0dda28f2"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/nette/utils/zipball/ce708655043c7050eb050df361c5e313cf708309",
|
"url": "https://api.github.com/repos/nette/utils/zipball/e67c4061eb40b9c113b218214e42cb5a0dda28f2",
|
||||||
"reference": "ce708655043c7050eb050df361c5e313cf708309",
|
"reference": "e67c4061eb40b9c113b218214e42cb5a0dda28f2",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
@@ -3960,9 +3959,9 @@
|
|||||||
],
|
],
|
||||||
"support": {
|
"support": {
|
||||||
"issues": "https://github.com/nette/utils/issues",
|
"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",
|
"name": "nunomaduro/collision",
|
||||||
|
|||||||
@@ -78,7 +78,7 @@ 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-06-01',
|
'version' => 'develop/2025-06-04',
|
||||||
'api_version' => '2.1.0', // field is no longer used.
|
'api_version' => '2.1.0', // field is no longer used.
|
||||||
'db_version' => 25,
|
'db_version' => 25,
|
||||||
|
|
||||||
|
|||||||
62
package-lock.json
generated
62
package-lock.json
generated
@@ -43,9 +43,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@babel/compat-data": {
|
"node_modules/@babel/compat-data": {
|
||||||
"version": "7.27.3",
|
"version": "7.27.5",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.27.3.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.27.5.tgz",
|
||||||
"integrity": "sha512-V42wFfx1ymFte+ecf6iXghnnP8kWTO+ZLXIyZq+1LAXHHvTZdVxicn4yiVYdYMGaCO3tmqub11AorKkv+iodqw==",
|
"integrity": "sha512-KiRAp/VoJaWkkte84TvUd9qjdbZAdiqyvMxrGl1N6vzFogKmaLgoM3L1kgtLicp2HP5fBJS8JrZKLVIZGVJAVg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"engines": {
|
"engines": {
|
||||||
@@ -94,13 +94,13 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@babel/generator": {
|
"node_modules/@babel/generator": {
|
||||||
"version": "7.27.3",
|
"version": "7.27.5",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.27.3.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.27.5.tgz",
|
||||||
"integrity": "sha512-xnlJYj5zepml8NXtjkG0WquFUv8RskFqyFcVgTBp5k+NaA/8uw/K+OSVf8AMGw5e9HKP2ETd5xpK5MLZQD6b4Q==",
|
"integrity": "sha512-ZGhA37l0e/g2s1Cnzdix0O3aLYm66eF8aufiVteOgnwxgnRP8GoyMj7VWsgWnQbVKXyge7hqrFh2K2TQM6t1Hw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/parser": "^7.27.3",
|
"@babel/parser": "^7.27.5",
|
||||||
"@babel/types": "^7.27.3",
|
"@babel/types": "^7.27.3",
|
||||||
"@jridgewell/gen-mapping": "^0.3.5",
|
"@jridgewell/gen-mapping": "^0.3.5",
|
||||||
"@jridgewell/trace-mapping": "^0.3.25",
|
"@jridgewell/trace-mapping": "^0.3.25",
|
||||||
@@ -406,9 +406,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@babel/parser": {
|
"node_modules/@babel/parser": {
|
||||||
"version": "7.27.4",
|
"version": "7.27.5",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.27.4.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.27.5.tgz",
|
||||||
"integrity": "sha512-BRmLHGwpUqLFR2jzx9orBuX/ABDkj2jLKOXrHDTN2aOKL+jFDDKaRNo9nyYsIl9h/UE/7lMKdDjKQQyxKKDZ7g==",
|
"integrity": "sha512-OsQd175SxWkGlzbny8J3K8TnnDD0N3lrIUtB92xwyRpzaenGZhxDvxN/JgU00U3CDZNj9tPuDJ5H0WS4Nt3vKg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@@ -683,9 +683,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@babel/plugin-transform-block-scoping": {
|
"node_modules/@babel/plugin-transform-block-scoping": {
|
||||||
"version": "7.27.3",
|
"version": "7.27.5",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.27.3.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.27.5.tgz",
|
||||||
"integrity": "sha512-+F8CnfhuLhwUACIJMLWnjz6zvzYM2r0yeIHKlbgfw7ml8rOMJsXNXV/hyRcb3nb493gRs4WvYpQAndWj/qQmkQ==",
|
"integrity": "sha512-JF6uE2s67f0y2RZcm2kpAUEbD50vH62TyWVebxwHAlbSdM49VqPz8t4a1uIjp4NIOIZ4xzLfjY5emt/RCyC7TQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@@ -1255,9 +1255,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@babel/plugin-transform-regenerator": {
|
"node_modules/@babel/plugin-transform-regenerator": {
|
||||||
"version": "7.27.4",
|
"version": "7.27.5",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.27.4.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.27.5.tgz",
|
||||||
"integrity": "sha512-Glp/0n8xuj+E1588otw5rjJkTXfzW7FjH3IIUrfqiZOPQCd2vbg8e+DQE8jK9g4V5/zrxFW+D9WM9gboRPELpQ==",
|
"integrity": "sha512-uhB8yHerfe3MWnuLAhEbeQ4afVoqv8BQsPqrTv7e/jZ9y00kJL6l9a/f4OWaKxotmjzewfEyXE1vgDJenkQ2/Q==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@@ -4417,9 +4417,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/caniuse-lite": {
|
"node_modules/caniuse-lite": {
|
||||||
"version": "1.0.30001720",
|
"version": "1.0.30001721",
|
||||||
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001720.tgz",
|
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001721.tgz",
|
||||||
"integrity": "sha512-Ec/2yV2nNPwb4DnTANEV99ZWwm3ZWfdlfkQbWSDDt+PsXEVYwlhPH8tdMaPunYTKKmz7AnHi2oNEi1GcmKCD8g==",
|
"integrity": "sha512-cOuvmUVtKrtEaoKiO0rSc29jcjwMwX5tOHDy4MgVFEWiUXj4uBMJkwI8MDySkgXidpMiHUcviogAvFi4pA2hDQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
@@ -5632,9 +5632,9 @@
|
|||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/electron-to-chromium": {
|
"node_modules/electron-to-chromium": {
|
||||||
"version": "1.5.161",
|
"version": "1.5.165",
|
||||||
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.161.tgz",
|
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.165.tgz",
|
||||||
"integrity": "sha512-hwtetwfKNZo/UlwHIVBlKZVdy7o8bIZxxKs0Mv/ROPiQQQmDgdm5a+KvKtBsxM8ZjFzTaCeLoodZ8jiBE3o9rA==",
|
"integrity": "sha512-naiMx1Z6Nb2TxPU6fiFrUrDTjyPMLdTtaOd2oLmG8zVSg2hCWGkhPyxwk+qRmZ1ytwVqUv0u7ZcDA5+ALhaUtw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "ISC"
|
"license": "ISC"
|
||||||
},
|
},
|
||||||
@@ -7713,9 +7713,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/laravel-vite-plugin": {
|
"node_modules/laravel-vite-plugin": {
|
||||||
"version": "1.2.0",
|
"version": "1.3.0",
|
||||||
"resolved": "https://registry.npmjs.org/laravel-vite-plugin/-/laravel-vite-plugin-1.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/laravel-vite-plugin/-/laravel-vite-plugin-1.3.0.tgz",
|
||||||
"integrity": "sha512-R0pJ+IcTVeqEMoKz/B2Ij57QVq3sFTABiFmb06gAwFdivbOgsUtuhX6N2MGLEArajrS3U5JbberzwOe7uXHMHQ==",
|
"integrity": "sha512-P5qyG56YbYxM8OuYmK2OkhcKe0AksNVJUjq9LUZ5tOekU9fBn9LujYyctI4t9XoLjuMvHJXXpCoPntY1oKltuA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@@ -10414,9 +10414,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/shell-quote": {
|
"node_modules/shell-quote": {
|
||||||
"version": "1.8.2",
|
"version": "1.8.3",
|
||||||
"resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.2.tgz",
|
"resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.3.tgz",
|
||||||
"integrity": "sha512-AzqKpGKjrj7EM6rKVQEPpB288oCfnrEIuyoT9cyF4nmGa7V8Zk6f7RRqYisX8X9m+Q7bd632aZW4ky7EhbQztA==",
|
"integrity": "sha512-ObmnIF4hXNg1BqhnHmgbDETF8dLPCggZWBjkQfhZpbszZnYur5DUljTcCHii5LC3J5E0yeO/1LIMyH+UvHQgyw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"engines": {
|
"engines": {
|
||||||
@@ -12081,9 +12081,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/webpack/node_modules/webpack-sources": {
|
"node_modules/webpack/node_modules/webpack-sources": {
|
||||||
"version": "3.3.0",
|
"version": "3.3.2",
|
||||||
"resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.3.2.tgz",
|
||||||
"integrity": "sha512-77R0RDmJfj9dyv5p3bM5pOHa+X8/ZkO9c7kpDstigkC4nIDobadsfSGCwB4bKhMVxqAok8tajaoR8rirM7+VFQ==",
|
"integrity": "sha512-ykKKus8lqlgXX/1WjudpIEjqsafjOTcOJqxnAbMLAu/KCsDCJ6GBtvscewvTkrn24HsnvFwrSCbenFrhtcCsAA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"engines": {
|
"engines": {
|
||||||
|
|||||||
@@ -24,4 +24,12 @@ $(function () {
|
|||||||
if (typeof(lineChart) === 'function' && typeof(piggyBankID) !== 'undefined') {
|
if (typeof(lineChart) === 'function' && typeof(piggyBankID) !== 'undefined') {
|
||||||
lineChart('chart/piggy-bank/' + piggyBankID, 'piggy-bank-history');
|
lineChart('chart/piggy-bank/' + piggyBankID, 'piggy-bank-history');
|
||||||
}
|
}
|
||||||
});
|
|
||||||
|
// on submit of logout button:
|
||||||
|
$('.reset-link').click(function(e) {
|
||||||
|
console.log('here we are');
|
||||||
|
e.preventDefault();
|
||||||
|
document.getElementById('reset-form').submit();
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|||||||
@@ -490,7 +490,6 @@ let transactions = function () {
|
|||||||
// addedSplit, is called from the HTML
|
// addedSplit, is called from the HTML
|
||||||
// for source account
|
// for source account
|
||||||
const renderAccount = function (item, b, c) {
|
const renderAccount = function (item, b, c) {
|
||||||
console.log('render account');
|
|
||||||
return item.name_with_balance + '<br><small class="text-muted">' + i18next.t('firefly.account_type_' + item.type) + '</small>';
|
return item.name_with_balance + '<br><small class="text-muted">' + i18next.t('firefly.account_type_' + item.type) + '</small>';
|
||||||
};
|
};
|
||||||
console.log('here we are in');
|
console.log('here we are in');
|
||||||
@@ -499,7 +498,7 @@ let transactions = function () {
|
|||||||
serverUrl: urls.account,
|
serverUrl: urls.account,
|
||||||
onRenderItem: renderAccount,
|
onRenderItem: renderAccount,
|
||||||
valueField: 'id',
|
valueField: 'id',
|
||||||
labelField: 'title',
|
labelField: 'name_with_balance',
|
||||||
onChange: changeSourceAccount,
|
onChange: changeSourceAccount,
|
||||||
onSelectItem: selectSourceAccount,
|
onSelectItem: selectSourceAccount,
|
||||||
hiddenValue: this.entries[count].source_account.alpine_name
|
hiddenValue: this.entries[count].source_account.alpine_name
|
||||||
@@ -509,7 +508,7 @@ let transactions = function () {
|
|||||||
serverUrl: urls.account,
|
serverUrl: urls.account,
|
||||||
account_types: this.filters.destination,
|
account_types: this.filters.destination,
|
||||||
valueField: 'id',
|
valueField: 'id',
|
||||||
labelField: 'title',
|
labelField: 'name_with_balance',
|
||||||
onRenderItem: renderAccount,
|
onRenderItem: renderAccount,
|
||||||
onChange: changeDestinationAccount,
|
onChange: changeDestinationAccount,
|
||||||
onSelectItem: selectDestinationAccount
|
onSelectItem: selectDestinationAccount
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ export function addAutocomplete(options) {
|
|||||||
liveServer: true,
|
liveServer: true,
|
||||||
};
|
};
|
||||||
if (typeof options.account_types !== 'undefined' && options.account_types.length > 0) {
|
if (typeof options.account_types !== 'undefined' && options.account_types.length > 0) {
|
||||||
params.serverParams['filter[account_types]'] = options.account_types;
|
params.serverParams['types'] = options.account_types;
|
||||||
}
|
}
|
||||||
if (typeof options.onRenderItem !== 'undefined' && null !== options.onRenderItem) {
|
if (typeof options.onRenderItem !== 'undefined' && null !== options.onRenderItem) {
|
||||||
console.log('overrule onRenderItem.');
|
console.log('overrule onRenderItem.');
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ export function changeDestinationAccount(item, ac) {
|
|||||||
export function selectDestinationAccount(item, ac) {
|
export function selectDestinationAccount(item, ac) {
|
||||||
const index = parseInt(ac._searchInput.attributes['data-index'].value);
|
const index = parseInt(ac._searchInput.attributes['data-index'].value);
|
||||||
document.querySelector('#form')._x_dataStack[0].$data.entries[index].destination_account = {
|
document.querySelector('#form')._x_dataStack[0].$data.entries[index].destination_account = {
|
||||||
id: item.id, name: item.title, alpine_name: item.title, type: item.meta.type, currency_code: item.meta.currency_code,
|
id: item.id, name: item.name, alpine_name: item.name, type: item.type, currency_code: item.currency_code,
|
||||||
};
|
};
|
||||||
document.querySelector('#form')._x_dataStack[0].changedDestinationAccount();
|
document.querySelector('#form')._x_dataStack[0].changedDestinationAccount();
|
||||||
}
|
}
|
||||||
@@ -78,7 +78,7 @@ export function changeSourceAccount(item, ac) {
|
|||||||
export function selectSourceAccount(item, ac) {
|
export function selectSourceAccount(item, ac) {
|
||||||
const index = parseInt(ac._searchInput.attributes['data-index'].value);
|
const index = parseInt(ac._searchInput.attributes['data-index'].value);
|
||||||
document.querySelector('#form')._x_dataStack[0].$data.entries[index].source_account = {
|
document.querySelector('#form')._x_dataStack[0].$data.entries[index].source_account = {
|
||||||
id: item.id, name: item.title, alpine_name: item.title, type: item.meta.type, currency_code: item.meta.currency_code,
|
id: item.id, name: item.name, alpine_name: item.name, type: item.type, currency_code: item.currency_code,
|
||||||
};
|
};
|
||||||
document.querySelector('#form')._x_dataStack[0].changedSourceAccount();
|
document.querySelector('#form')._x_dataStack[0].changedSourceAccount();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,8 +36,8 @@ export default defineConfig(({command, mode, isSsrBuild, isPreview}) => {
|
|||||||
let https = null;
|
let https = null;
|
||||||
if (command === 'serve') {
|
if (command === 'serve') {
|
||||||
https = {
|
https = {
|
||||||
key: fs.readFileSync(`/Users/sander/Sites/vm/tls-certificates/wildcard.sd.internal.key`),
|
key: fs.readFileSync(`/vagrant/tls-certificates/wildcard.sd.internal.key`),
|
||||||
cert: fs.readFileSync(`/Users/sander/Sites/vm/tls-certificates/wildcard.sd.internal.crt`),
|
cert: fs.readFileSync(`/vagrant/tls-certificates/wildcard.sd.internal.crt`),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -83,7 +83,7 @@ export default defineConfig(({command, mode, isSsrBuild, isPreview}) => {
|
|||||||
|
|
||||||
server: {
|
server: {
|
||||||
cors: true,
|
cors: true,
|
||||||
origin: 'https://localhost:5173',
|
origin: 'https://192.168.96.154:5173',
|
||||||
watch: {
|
watch: {
|
||||||
usePolling: true,
|
usePolling: true,
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -70,7 +70,7 @@ return [
|
|||||||
// known user login attempt
|
// known user login attempt
|
||||||
'failed_login_subject' => 'Firefly III detected a failed login attempt',
|
'failed_login_subject' => 'Firefly III detected a failed login attempt',
|
||||||
'failed_login_body' => 'Firefly III detected that somebody (you?) failed to login with your account ":email". Please verify that this was you.',
|
'failed_login_body' => 'Firefly III detected that somebody (you?) failed to login with your account ":email". Please verify that this was you.',
|
||||||
'failed_login_message' => 'A failed login attempt on your Firefly III account ":email" was detected.',
|
'failed_login_message' => 'A failed login attempt (:ip) on your Firefly III account ":email" was detected.',
|
||||||
'failed_login_warning' => 'If you recognize this IP address or the login attempt, you can ignore this message. If you didn\'t try to login, of if you have no idea what this is about, verify your password security, change it, and log out all other sessions. To do this, go to your profile page. Of course you have 2FA enabled already, right? Stay safe!',
|
'failed_login_warning' => 'If you recognize this IP address or the login attempt, you can ignore this message. If you didn\'t try to login, of if you have no idea what this is about, verify your password security, change it, and log out all other sessions. To do this, go to your profile page. Of course you have 2FA enabled already, right? Stay safe!',
|
||||||
|
|
||||||
// registered
|
// registered
|
||||||
|
|||||||
@@ -2486,6 +2486,10 @@ return [
|
|||||||
'left_for_piggy_banks' => 'Left for piggy banks',
|
'left_for_piggy_banks' => 'Left for piggy banks',
|
||||||
'sum_of_piggy_banks' => 'Sum of piggy banks',
|
'sum_of_piggy_banks' => 'Sum of piggy banks',
|
||||||
'saved_so_far' => 'Saved so far',
|
'saved_so_far' => 'Saved so far',
|
||||||
|
'saved_so_far_total' => 'Saved so far in total',
|
||||||
|
'reset_history' => 'reset history',
|
||||||
|
'reset_history_confirm' => 'Are you sure you want to reset the history of this piggy bank? This will make the chart match the piggy bank\'s amount again.',
|
||||||
|
'piggy_history_reset' => 'The piggy bank history has been reset',
|
||||||
'left_to_save' => 'Left to save',
|
'left_to_save' => 'Left to save',
|
||||||
'suggested_amount' => 'Suggested monthly amount to save',
|
'suggested_amount' => 'Suggested monthly amount to save',
|
||||||
'add_money_to_piggy_title' => 'Add money to piggy bank ":name"',
|
'add_money_to_piggy_title' => 'Add money to piggy bank ":name"',
|
||||||
|
|||||||
@@ -68,6 +68,7 @@ return [
|
|||||||
'cannot_find_piggy' => 'Firefly III can\'t find a piggy bank named ":name"',
|
'cannot_find_piggy' => 'Firefly III can\'t find a piggy bank named ":name"',
|
||||||
'no_link_piggy' => 'This transaction\'s accounts are not linked to the piggy bank, so no action will be taken',
|
'no_link_piggy' => 'This transaction\'s accounts are not linked to the piggy bank, so no action will be taken',
|
||||||
'both_link_piggy' => 'This transaction\'s accounts are both linked to the piggy bank, so no action will be taken',
|
'both_link_piggy' => 'This transaction\'s accounts are both linked to the piggy bank, so no action will be taken',
|
||||||
|
'already_linked' => 'This transaction is already linked to piggy bank ":name"',
|
||||||
'cannot_unlink_tag' => 'Tag ":tag" isn\'t linked to this transaction',
|
'cannot_unlink_tag' => 'Tag ":tag" isn\'t linked to this transaction',
|
||||||
'cannot_find_budget' => 'Firefly III can\'t find budget ":name"',
|
'cannot_find_budget' => 'Firefly III can\'t find budget ":name"',
|
||||||
'cannot_find_category' => 'Firefly III can\'t find category ":name"',
|
'cannot_find_category' => 'Firefly III can\'t find category ":name"',
|
||||||
|
|||||||
@@ -163,6 +163,7 @@
|
|||||||
{% endif %}
|
{% endif %}
|
||||||
</td>
|
</td>
|
||||||
<td style="{{ style|raw }};text-align:right">
|
<td style="{{ style|raw }};text-align:right">
|
||||||
|
|
||||||
{# deposit #}
|
{# deposit #}
|
||||||
{% if transaction.transaction_type_type == 'Deposit' %}
|
{% if transaction.transaction_type_type == 'Deposit' %}
|
||||||
{# amount of deposit #}
|
{# amount of deposit #}
|
||||||
|
|||||||
@@ -54,8 +54,20 @@
|
|||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
{% for account in piggy.accounts %}
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
{{ 'saved_so_far'|_ }}
|
||||||
|
(<a href="{{ route('accounts.show', account.id) }}">{{ account.name }}</a>)
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
{{ formatAmountBySymbol(account.current_amount, piggy.currency_symbol, piggy.currency_decimal_places) }}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
{% endfor %}
|
||||||
<tr>
|
<tr>
|
||||||
<td>{{ 'saved_so_far'|_ }}</td>
|
<td>{{ 'saved_so_far_total'|_ }}</td>
|
||||||
<td>
|
<td>
|
||||||
{{ formatAmountBySymbol(piggy.current_amount, piggy.currency_symbol, piggy.currency_decimal_places) }}
|
{{ formatAmountBySymbol(piggy.current_amount, piggy.currency_symbol, piggy.currency_decimal_places) }}
|
||||||
</td>
|
</td>
|
||||||
@@ -102,7 +114,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="box">
|
<div class="box">
|
||||||
<div class="box-header with-border">
|
<div class="box-header with-border">
|
||||||
<h3 class="box-title">{{ 'event_history'|_ }}</h3>
|
<h3 class="box-title">{{ 'event_history'|_ }} (<a onclick="return confirm('{{ 'reset_history_confirm'|_|escape('js') }}');" class="reset-link" href="#">{{ 'reset_history'|_ }}</a>)</h3>
|
||||||
</div>
|
</div>
|
||||||
<div class="box-body no-padding" id="piggyEvents">
|
<div class="box-body no-padding" id="piggyEvents">
|
||||||
{% include 'list/piggy-bank-events' %}
|
{% include 'list/piggy-bank-events' %}
|
||||||
@@ -140,6 +152,9 @@
|
|||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
|
<form id="reset-form" action="{{ route('piggy-banks.reset', [piggyBank.id]) }}" method="POST" style="display: none;">
|
||||||
|
<input type="hidden" name="_token" value="{{ csrf_token() }}"/>
|
||||||
|
</form>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block scripts %}
|
{% block scripts %}
|
||||||
|
|||||||
@@ -803,6 +803,7 @@ Route::group(
|
|||||||
Route::post('store', ['uses' => 'PiggyBank\CreateController@store', 'as' => 'store']);
|
Route::post('store', ['uses' => 'PiggyBank\CreateController@store', 'as' => 'store']);
|
||||||
Route::post('update/{piggyBank}', ['uses' => 'PiggyBank\EditController@update', 'as' => 'update']);
|
Route::post('update/{piggyBank}', ['uses' => 'PiggyBank\EditController@update', 'as' => 'update']);
|
||||||
Route::post('destroy/{piggyBank}', ['uses' => 'PiggyBank\DeleteController@destroy', 'as' => 'destroy']);
|
Route::post('destroy/{piggyBank}', ['uses' => 'PiggyBank\DeleteController@destroy', 'as' => 'destroy']);
|
||||||
|
Route::post('reset-history/{piggyBank}', ['uses' => 'PiggyBank\EditController@resetHistory', 'as' => 'reset']);
|
||||||
Route::post('add/{piggyBank}', ['uses' => 'PiggyBank\AmountController@postAdd', 'as' => 'add']);
|
Route::post('add/{piggyBank}', ['uses' => 'PiggyBank\AmountController@postAdd', 'as' => 'add']);
|
||||||
Route::post('remove/{piggyBank}', ['uses' => 'PiggyBank\AmountController@postRemove', 'as' => 'remove']);
|
Route::post('remove/{piggyBank}', ['uses' => 'PiggyBank\AmountController@postRemove', 'as' => 'remove']);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user