mirror of
https://github.com/firefly-iii/firefly-iii.git
synced 2025-02-25 18:45:27 -06:00
Merge branch 'release/5.7.16'
This commit is contained in:
commit
265d973811
11
.env.example
11
.env.example
@ -195,6 +195,15 @@ AUTHENTICATION_GUARD=web
|
||||
AUTHENTICATION_GUARD_HEADER=REMOTE_USER
|
||||
AUTHENTICATION_GUARD_EMAIL=
|
||||
|
||||
#
|
||||
# Firefly III generates a basic keypair for your OAuth tokens.
|
||||
# If you want, you can overrule the key with your own (secure) value.
|
||||
# It's also possible to set PASSPORT_PUBLIC_KEY_FILE or PASSPORT_PRIVATE_KEY_FILE
|
||||
# if you're using Docker secrets or similar solutions for secret management
|
||||
#
|
||||
PASSPORT_PRIVATE_KEY=
|
||||
PASSPORT_PUBLIC_KEY=
|
||||
|
||||
#
|
||||
# Extra authentication settings
|
||||
#
|
||||
@ -236,7 +245,7 @@ ALLOW_WEBHOOKS=false
|
||||
STATIC_CRON_TOKEN=
|
||||
|
||||
# You can fine tune the start-up of a Docker container by editing these environment variables.
|
||||
# Use this at your own risk. Disabling certain checks and features may result in lost of inconsistent data.
|
||||
# Use this at your own risk. Disabling certain checks and features may result in lots of inconsistent data.
|
||||
# However if you know what you're doing you can significantly speed up container start times.
|
||||
# Set each value to true to enable, or false to disable.
|
||||
|
||||
|
2
.github/security.md
vendored
2
.github/security.md
vendored
@ -40,7 +40,7 @@ The Firefly III developer will respond to vulnerability reports as follows:
|
||||
9. Once the fix is confirmed, the developer will patch the vulnerability in the next patch or minor release. Upon release of the patched version of Firefly III, we will follow the **Public Disclosure Process**.
|
||||
|
||||
### Public Disclosure Process
|
||||
The developer publishes a public [advisory](https://github.com/firefly-iii/firefly-iii/security/advisories) to the Firefly III community via GitHub. In most cases, additional communication via Twitter, reddit and other channels will assist in educating Firefly III users and rolling out the patched release to affected users.
|
||||
The developer publishes a public [advisory](https://github.com/firefly-iii/firefly-iii/security/advisories) to the Firefly III community via GitHub. In most cases, additional communication via Mastodon, Gitter and other channels will assist in educating Firefly III users and rolling out the patched release to affected users.
|
||||
|
||||
The develop will also publish any mitigating steps users can take until the fix can be applied to their Firefly III instances.
|
||||
|
||||
|
@ -127,11 +127,11 @@ class AccountController extends Controller
|
||||
];
|
||||
$currentStart = clone $start;
|
||||
$range = app('steam')->balanceInRange($account, $start, clone $end);
|
||||
$previous = round((float) array_values($range)[0], 12);
|
||||
$previous = $range[0] ?? '0';
|
||||
while ($currentStart <= $end) {
|
||||
$format = $currentStart->format('Y-m-d');
|
||||
$label = $currentStart->toAtomString();
|
||||
$balance = array_key_exists($format, $range) ? round((float) $range[$format], 12) : $previous;
|
||||
$balance = array_key_exists($format, $range) ? $range[$format] : $previous;
|
||||
$previous = $balance;
|
||||
$currentStart->addDay();
|
||||
$currentSet['entries'][$label] = $balance;
|
||||
|
@ -162,6 +162,7 @@ class DestroyController extends Controller
|
||||
);
|
||||
break;
|
||||
}
|
||||
app('preferences')->mark();
|
||||
|
||||
return response()->json([], 204);
|
||||
}
|
||||
|
@ -94,7 +94,7 @@ class AccountController extends Controller
|
||||
'id' => (string) $expense['id'],
|
||||
'name' => $expense['name'],
|
||||
'difference' => $expense['sum'],
|
||||
'difference_float' => (float) $expense['sum'],
|
||||
'difference_float' => (float) $expense['sum'], // intentional float
|
||||
'currency_id' => (string) $expense['currency_id'],
|
||||
'currency_code' => $expense['currency_code'],
|
||||
];
|
||||
@ -126,7 +126,7 @@ class AccountController extends Controller
|
||||
'id' => (string) $expense['id'],
|
||||
'name' => $expense['name'],
|
||||
'difference' => $expense['sum'],
|
||||
'difference_float' => (float) $expense['sum'],
|
||||
'difference_float' => (float) $expense['sum'], // intentional float
|
||||
'currency_id' => (string) $expense['currency_id'],
|
||||
'currency_code' => $expense['currency_code'],
|
||||
];
|
||||
|
@ -101,7 +101,7 @@ class BillController extends Controller
|
||||
'currency_code' => $journal['currency_code'],
|
||||
];
|
||||
$response[$key]['difference'] = bcadd($response[$key]['difference'], $journal['amount']);
|
||||
$response[$key]['difference_float'] = (float) $response[$key]['difference'];
|
||||
$response[$key]['difference_float'] = (float) $response[$key]['difference']; // intentional float
|
||||
}
|
||||
if (0 !== $foreignCurrencyId) {
|
||||
$response[$foreignKey] = $response[$foreignKey] ?? [
|
||||
@ -111,7 +111,7 @@ class BillController extends Controller
|
||||
'currency_code' => $journal['foreign_currency_code'],
|
||||
];
|
||||
$response[$foreignKey]['difference'] = bcadd($response[$foreignKey]['difference'], $journal['foreign_amount']);
|
||||
$response[$foreignKey]['difference_float'] = (float) $response[$foreignKey]['difference'];
|
||||
$response[$foreignKey]['difference_float'] = (float) $response[$foreignKey]['difference']; // intentional float
|
||||
}
|
||||
}
|
||||
|
||||
@ -154,7 +154,7 @@ class BillController extends Controller
|
||||
'currency_code' => $journal['currency_code'],
|
||||
];
|
||||
$response[$currencyId]['difference'] = bcadd($response[$currencyId]['difference'], $journal['amount']);
|
||||
$response[$currencyId]['difference_float'] = (float) $response[$currencyId]['difference'];
|
||||
$response[$currencyId]['difference_float'] = (float) $response[$currencyId]['difference']; // intentional float
|
||||
}
|
||||
if (0 !== $foreignCurrencyId) {
|
||||
$response[$foreignCurrencyId] = $response[$foreignCurrencyId] ?? [
|
||||
@ -164,7 +164,7 @@ class BillController extends Controller
|
||||
'currency_code' => $journal['foreign_currency_code'],
|
||||
];
|
||||
$response[$foreignCurrencyId]['difference'] = bcadd($response[$foreignCurrencyId]['difference'], $journal['foreign_amount']);
|
||||
$response[$foreignCurrencyId]['difference_float'] = (float) $response[$foreignCurrencyId]['difference'];
|
||||
$response[$foreignCurrencyId]['difference_float'] = (float) $response[$foreignCurrencyId]['difference']; // intentional float
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -91,7 +91,7 @@ class BudgetController extends Controller
|
||||
'id' => (string) $budget->id,
|
||||
'name' => $budget->name,
|
||||
'difference' => $expense['sum'],
|
||||
'difference_float' => (float) $expense['sum'],
|
||||
'difference_float' => (float) $expense['sum'], // intentional float
|
||||
'currency_id' => (string) $expense['currency_id'],
|
||||
'currency_code' => $expense['currency_code'],
|
||||
];
|
||||
@ -120,7 +120,7 @@ class BudgetController extends Controller
|
||||
foreach ($expenses as $expense) {
|
||||
$result[] = [
|
||||
'difference' => $expense['sum'],
|
||||
'difference_float' => (float) $expense['sum'],
|
||||
'difference_float' => (float) $expense['sum'], // intentional float
|
||||
'currency_id' => (string) $expense['currency_id'],
|
||||
'currency_code' => $expense['currency_code'],
|
||||
];
|
||||
|
@ -92,7 +92,7 @@ class CategoryController extends Controller
|
||||
'id' => (string) $category->id,
|
||||
'name' => $category->name,
|
||||
'difference' => $expense['sum'],
|
||||
'difference_float' => (float) $expense['sum'],
|
||||
'difference_float' => (float) $expense['sum'], // intentional float
|
||||
'currency_id' => (string) $expense['currency_id'],
|
||||
'currency_code' => $expense['currency_code'],
|
||||
];
|
||||
@ -121,7 +121,7 @@ class CategoryController extends Controller
|
||||
foreach ($expenses as $expense) {
|
||||
$result[] = [
|
||||
'difference' => $expense['sum'],
|
||||
'difference_float' => (float) $expense['sum'],
|
||||
'difference_float' => (float) $expense['sum'], // intentional float
|
||||
'currency_id' => (string) $expense['currency_id'],
|
||||
'currency_code' => $expense['currency_code'],
|
||||
];
|
||||
|
@ -66,7 +66,7 @@ class PeriodController extends Controller
|
||||
'currency_code' => $journal['currency_code'],
|
||||
];
|
||||
$response[$currencyId]['difference'] = bcadd($response[$currencyId]['difference'], $journal['amount']);
|
||||
$response[$currencyId]['difference_float'] = (float) $response[$currencyId]['difference'];
|
||||
$response[$currencyId]['difference_float'] = (float) $response[$currencyId]['difference']; // intentional float
|
||||
}
|
||||
if (0 !== $foreignCurrencyId) {
|
||||
$response[$foreignCurrencyId] = $response[$foreignCurrencyId] ?? [
|
||||
@ -76,7 +76,7 @@ class PeriodController extends Controller
|
||||
'currency_code' => $journal['foreign_currency_code'],
|
||||
];
|
||||
$response[$foreignCurrencyId]['difference'] = bcadd($response[$foreignCurrencyId]['difference'], $journal['foreign_amount']);
|
||||
$response[$foreignCurrencyId]['difference_float'] = (float) $response[$foreignCurrencyId]['difference'];
|
||||
$response[$foreignCurrencyId]['difference_float'] = (float) $response[$foreignCurrencyId]['difference']; // intentional float
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -171,7 +171,7 @@ class TagController extends Controller
|
||||
$response[$foreignKey]['difference'] = bcadd(
|
||||
$response[$foreignKey]['difference'], app('steam')->positive($journal['foreign_amount'])
|
||||
);
|
||||
$response[$foreignKey]['difference_float'] = (float) $response[$foreignKey]['difference'];
|
||||
$response[$foreignKey]['difference_float'] = (float) $response[$foreignKey]['difference']; // intentional float
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -69,6 +69,7 @@ class DestroyController extends Controller
|
||||
public function destroy(Account $account): JsonResponse
|
||||
{
|
||||
$this->repository->destroy($account, null);
|
||||
app('preferences')->mark();
|
||||
|
||||
return response()->json([], 204);
|
||||
}
|
||||
|
@ -73,6 +73,7 @@ class DestroyController extends Controller
|
||||
public function destroy(Attachment $attachment): JsonResponse
|
||||
{
|
||||
$this->repository->destroy($attachment);
|
||||
app('preferences')->mark();
|
||||
|
||||
return response()->json([], 204);
|
||||
}
|
||||
|
@ -71,6 +71,7 @@ class DestroyController extends Controller
|
||||
public function destroy(AvailableBudget $availableBudget): JsonResponse
|
||||
{
|
||||
$this->abRepository->destroyAvailableBudget($availableBudget);
|
||||
app('preferences')->mark();
|
||||
|
||||
return response()->json([], 204);
|
||||
}
|
||||
|
@ -67,6 +67,7 @@ class DestroyController extends Controller
|
||||
public function destroy(Bill $bill): JsonResponse
|
||||
{
|
||||
$this->repository->destroy($bill);
|
||||
app('preferences')->mark();
|
||||
|
||||
return response()->json([], 204);
|
||||
}
|
||||
|
@ -67,6 +67,7 @@ class DestroyController extends Controller
|
||||
public function destroy(Budget $budget): JsonResponse
|
||||
{
|
||||
$this->repository->destroy($budget);
|
||||
app('preferences')->mark();
|
||||
|
||||
return response()->json([], 204);
|
||||
}
|
||||
|
@ -77,6 +77,7 @@ class DestroyController extends Controller
|
||||
throw new FireflyException('20028: The budget limit does not belong to the budget.');
|
||||
}
|
||||
$this->blRepository->destroyBudgetLimit($budgetLimit);
|
||||
app('preferences')->mark();
|
||||
|
||||
return response()->json([], 204);
|
||||
}
|
||||
|
@ -67,6 +67,7 @@ class DestroyController extends Controller
|
||||
public function destroy(Category $category): JsonResponse
|
||||
{
|
||||
$this->repository->destroy($category);
|
||||
app('preferences')->mark();
|
||||
|
||||
return response()->json([], 204);
|
||||
}
|
||||
|
@ -70,6 +70,7 @@ class DestroyController extends Controller
|
||||
public function destroy(ObjectGroup $objectGroup): JsonResponse
|
||||
{
|
||||
$this->repository->destroy($objectGroup);
|
||||
app('preferences')->mark();
|
||||
|
||||
return response()->json([], 204);
|
||||
}
|
||||
|
@ -67,6 +67,7 @@ class DestroyController extends Controller
|
||||
public function destroy(PiggyBank $piggyBank): JsonResponse
|
||||
{
|
||||
$this->repository->destroy($piggyBank);
|
||||
app('preferences')->mark();
|
||||
|
||||
return response()->json([], 204);
|
||||
}
|
||||
|
@ -67,6 +67,7 @@ class DestroyController extends Controller
|
||||
public function destroy(Recurrence $recurrence): JsonResponse
|
||||
{
|
||||
$this->repository->destroy($recurrence);
|
||||
app('preferences')->mark();
|
||||
|
||||
return response()->json([], 204);
|
||||
}
|
||||
|
@ -71,6 +71,7 @@ class DestroyController extends Controller
|
||||
public function destroy(Rule $rule): JsonResponse
|
||||
{
|
||||
$this->ruleRepository->destroy($rule);
|
||||
app('preferences')->mark();
|
||||
|
||||
return response()->json([], 204);
|
||||
}
|
||||
|
@ -71,6 +71,7 @@ class DestroyController extends Controller
|
||||
public function destroy(RuleGroup $ruleGroup): JsonResponse
|
||||
{
|
||||
$this->ruleGroupRepository->destroy($ruleGroup, null);
|
||||
app('preferences')->mark();
|
||||
|
||||
return response()->json([], 204);
|
||||
}
|
||||
|
@ -71,6 +71,7 @@ class DestroyController extends Controller
|
||||
public function destroy(Tag $tag): JsonResponse
|
||||
{
|
||||
$this->repository->destroy($tag);
|
||||
app('preferences')->mark();
|
||||
|
||||
return response()->json([], 204);
|
||||
}
|
||||
|
@ -122,6 +122,7 @@ class DestroyController extends Controller
|
||||
public function destroyJournal(TransactionJournal $transactionJournal): JsonResponse
|
||||
{
|
||||
$this->repository->destroyJournal($transactionJournal);
|
||||
app('preferences')->mark();
|
||||
|
||||
return response()->json([], 204);
|
||||
}
|
||||
|
@ -88,6 +88,7 @@ class DestroyController extends Controller
|
||||
}
|
||||
|
||||
$this->repository->destroy($currency);
|
||||
app('preferences')->mark();
|
||||
|
||||
return response()->json([], 204);
|
||||
}
|
||||
|
@ -71,6 +71,7 @@ class DestroyController extends Controller
|
||||
public function destroy(TransactionJournalLink $link): JsonResponse
|
||||
{
|
||||
$this->repository->destroyLink($link);
|
||||
app('preferences')->mark();
|
||||
|
||||
return response()->json([], 204);
|
||||
}
|
||||
|
@ -82,6 +82,7 @@ class DestroyController extends Controller
|
||||
throw new FireflyException('200020: Link type cannot be changed.');
|
||||
}
|
||||
$this->repository->destroy($linkType);
|
||||
app('preferences')->mark();
|
||||
|
||||
return response()->json([], 204);
|
||||
}
|
||||
|
@ -188,7 +188,7 @@ class BasicController extends Controller
|
||||
$return[] = [
|
||||
'key' => sprintf('balance-in-%s', $currency->code),
|
||||
'title' => trans('firefly.box_balance_in_currency', ['currency' => $currency->symbol]),
|
||||
'monetary_value' => round((float) $sums[$currencyId] ?? 0, $currency->decimal_places),
|
||||
'monetary_value' => $sums[$currencyId] ?? '0',
|
||||
'currency_id' => $currency->id,
|
||||
'currency_code' => $currency->code,
|
||||
'currency_symbol' => $currency->symbol,
|
||||
@ -201,7 +201,7 @@ class BasicController extends Controller
|
||||
$return[] = [
|
||||
'key' => sprintf('spent-in-%s', $currency->code),
|
||||
'title' => trans('firefly.box_spent_in_currency', ['currency' => $currency->symbol]),
|
||||
'monetary_value' => round((float) ($expenses[$currencyId] ?? 0), $currency->decimal_places),
|
||||
'monetary_value' => $expenses[$currencyId] ?? '0',
|
||||
'currency_id' => $currency->id,
|
||||
'currency_code' => $currency->code,
|
||||
'currency_symbol' => $currency->symbol,
|
||||
@ -213,7 +213,7 @@ class BasicController extends Controller
|
||||
$return[] = [
|
||||
'key' => sprintf('earned-in-%s', $currency->code),
|
||||
'title' => trans('firefly.box_earned_in_currency', ['currency' => $currency->symbol]),
|
||||
'monetary_value' => round((float) ($incomes[$currencyId] ?? 0), $currency->decimal_places),
|
||||
'monetary_value' => $incomes[$currencyId] ?? '0',
|
||||
'currency_id' => $currency->id,
|
||||
'currency_code' => $currency->code,
|
||||
'currency_symbol' => $currency->symbol,
|
||||
@ -251,7 +251,7 @@ class BasicController extends Controller
|
||||
$return[] = [
|
||||
'key' => sprintf('bills-paid-in-%s', $currency->code),
|
||||
'title' => trans('firefly.box_bill_paid_in_currency', ['currency' => $currency->symbol]),
|
||||
'monetary_value' => round((float) $amount, $currency->decimal_places),
|
||||
'monetary_value' => $amount,
|
||||
'currency_id' => $currency->id,
|
||||
'currency_code' => $currency->code,
|
||||
'currency_symbol' => $currency->symbol,
|
||||
@ -271,7 +271,7 @@ class BasicController extends Controller
|
||||
$return[] = [
|
||||
'key' => sprintf('bills-unpaid-in-%s', $currency->code),
|
||||
'title' => trans('firefly.box_bill_unpaid_in_currency', ['currency' => $currency->symbol]),
|
||||
'monetary_value' => round((float) $amount, $currency->decimal_places),
|
||||
'monetary_value' => $amount,
|
||||
'currency_id' => $currency->id,
|
||||
'currency_code' => $currency->code,
|
||||
'currency_symbol' => $currency->symbol,
|
||||
@ -315,7 +315,7 @@ class BasicController extends Controller
|
||||
$return[] = [
|
||||
'key' => sprintf('left-to-spend-in-%s', $row['currency_code']),
|
||||
'title' => trans('firefly.box_left_to_spend_in_currency', ['currency' => $row['currency_symbol']]),
|
||||
'monetary_value' => round((float) $leftToSpend, $row['currency_decimal_places']),
|
||||
'monetary_value' => $leftToSpend,
|
||||
'currency_id' => $row['currency_id'],
|
||||
'currency_code' => $row['currency_code'],
|
||||
'currency_symbol' => $row['currency_symbol'],
|
||||
@ -373,8 +373,8 @@ class BasicController extends Controller
|
||||
foreach ($netWorthSet as $data) {
|
||||
/** @var TransactionCurrency $currency */
|
||||
$currency = $data['currency'];
|
||||
$amount = round((float) $data['balance'], $currency->decimal_places);
|
||||
if (0.0 === $amount) {
|
||||
$amount = $data['balance'];
|
||||
if (0 === bccomp($amount, '0')) {
|
||||
continue;
|
||||
}
|
||||
// return stuff
|
||||
|
@ -69,6 +69,7 @@ class DestroyController extends Controller
|
||||
public function destroy(Webhook $webhook): JsonResponse
|
||||
{
|
||||
$this->repository->destroy($webhook);
|
||||
app('preferences')->mark();
|
||||
|
||||
return response()->json([], 204);
|
||||
}
|
||||
@ -98,6 +99,7 @@ class DestroyController extends Controller
|
||||
}
|
||||
|
||||
$this->repository->destroyAttempt($attempt);
|
||||
app('preferences')->mark();
|
||||
|
||||
return response()->json([], 204);
|
||||
}
|
||||
@ -121,6 +123,7 @@ class DestroyController extends Controller
|
||||
throw new FireflyException('Webhook and webhook message are no match');
|
||||
}
|
||||
$this->repository->destroyMessage($message);
|
||||
app('preferences')->mark();
|
||||
|
||||
return response()->json([], 204);
|
||||
}
|
||||
|
@ -104,9 +104,10 @@ class StoreRequest extends FormRequest
|
||||
$validator->after(
|
||||
static function (Validator $validator) {
|
||||
$data = $validator->getData();
|
||||
$min = (float) ($data['amount_min'] ?? 0);
|
||||
$max = (float) ($data['amount_max'] ?? 0);
|
||||
if ($min > $max) {
|
||||
$min = $data['amount_min'] ?? '0';
|
||||
$max = $data['amount_max'] ?? '0';
|
||||
|
||||
if (1 === bccomp($min, $max)) {
|
||||
$validator->errors()->add('amount_min', (string) trans('validation.amount_min_over_max'));
|
||||
}
|
||||
}
|
||||
|
@ -105,9 +105,10 @@ class UpdateRequest extends FormRequest
|
||||
static function (Validator $validator) {
|
||||
$data = $validator->getData();
|
||||
if (array_key_exists('amount_min', $data) && array_key_exists('amount_max', $data)) {
|
||||
$min = (float) ($data['amount_min'] ?? 0);
|
||||
$max = (float) ($data['amount_max'] ?? 0);
|
||||
if ($min > $max) {
|
||||
$min = $data['amount_min'] ?? '0';
|
||||
$max = $data['amount_max'] ?? '0';
|
||||
|
||||
if (1 === bccomp($min, $max)) {
|
||||
$validator->errors()->add('amount_min', (string) trans('validation.amount_min_over_max'));
|
||||
}
|
||||
}
|
||||
|
@ -84,7 +84,7 @@ class TestRequest extends FormRequest
|
||||
{
|
||||
return [
|
||||
'start' => 'date',
|
||||
'end' => 'date|after:start',
|
||||
'end' => 'date|after_or_equal:start',
|
||||
'accounts' => '',
|
||||
'accounts.*' => 'required|exists:accounts,id|belongsToUser:accounts',
|
||||
];
|
||||
|
@ -73,7 +73,7 @@ class TriggerRequest extends FormRequest
|
||||
{
|
||||
return [
|
||||
'start' => 'date',
|
||||
'end' => 'date|after:start',
|
||||
'end' => 'date|after_or_equal:start',
|
||||
'accounts' => '',
|
||||
'accounts.*' => 'exists:accounts,id|belongsToUser:accounts',
|
||||
];
|
||||
|
@ -73,7 +73,7 @@ class TestRequest extends FormRequest
|
||||
{
|
||||
return [
|
||||
'start' => 'date',
|
||||
'end' => 'date|after:start',
|
||||
'end' => 'date|after_or_equal:start',
|
||||
'accounts' => '',
|
||||
'accounts.*' => 'exists:accounts,id|belongsToUser:accounts',
|
||||
];
|
||||
|
@ -73,7 +73,7 @@ class TriggerRequest extends FormRequest
|
||||
{
|
||||
return [
|
||||
'start' => 'date',
|
||||
'end' => 'date|after:start',
|
||||
'end' => 'date|after_or_equal:start',
|
||||
];
|
||||
}
|
||||
|
||||
|
@ -46,6 +46,7 @@ class PreferenceStoreRequest extends FormRequest
|
||||
if ('false' === $array['data']) {
|
||||
$array['data'] = false;
|
||||
}
|
||||
// TODO remove float
|
||||
if (is_numeric($array['data'])) {
|
||||
$array['data'] = (float) $array['data'];
|
||||
}
|
||||
|
@ -47,6 +47,7 @@ class PreferenceUpdateRequest extends FormRequest
|
||||
if ('false' === $array['data']) {
|
||||
$array['data'] = false;
|
||||
}
|
||||
// TODO remove float
|
||||
if (is_numeric($array['data'])) {
|
||||
$array['data'] = (float) $array['data'];
|
||||
}
|
||||
|
@ -330,7 +330,7 @@ class MigrateToGroups extends Command
|
||||
{
|
||||
$set = $journal->transactions->filter(
|
||||
static function (Transaction $subject) use ($transaction) {
|
||||
$amount = (float) $transaction->amount * -1 === (float) $subject->amount;
|
||||
$amount = (float) $transaction->amount * -1 === (float) $subject->amount; // intentional float
|
||||
$identifier = $transaction->identifier === $subject->identifier;
|
||||
Log::debug(sprintf('Amount the same? %s', var_export($amount, true)));
|
||||
Log::debug(sprintf('ID the same? %s', var_export($identifier, true)));
|
||||
|
59
app/Events/ChangedPiggyBankAmount.php
Normal file
59
app/Events/ChangedPiggyBankAmount.php
Normal file
@ -0,0 +1,59 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
/*
|
||||
* ChangedPiggyBankAmount.php
|
||||
* Copyright (c) 2022 james@firefly-iii.org
|
||||
*
|
||||
* This file is part of Firefly III (https://github.com/firefly-iii).
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
namespace FireflyIII\Events;
|
||||
|
||||
use FireflyIII\Models\PiggyBank;
|
||||
use FireflyIII\Models\TransactionGroup;
|
||||
use FireflyIII\Models\TransactionJournal;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
/**
|
||||
* Class ChangedPiggyBankAmount
|
||||
*/
|
||||
class ChangedPiggyBankAmount extends Event
|
||||
{
|
||||
use SerializesModels;
|
||||
|
||||
public PiggyBank $piggyBank;
|
||||
public ?TransactionJournal $transactionJournal;
|
||||
public ?TransactionGroup $transactionGroup;
|
||||
public string $amount;
|
||||
|
||||
/**
|
||||
* Create a new event instance.
|
||||
*
|
||||
* @param PiggyBank $piggyBank
|
||||
* @param string $amount
|
||||
* @param TransactionJournal|null $transactionJournal
|
||||
* @param TransactionGroup|null $transactionGroup
|
||||
*/
|
||||
public function __construct(PiggyBank $piggyBank, string $amount, ?TransactionJournal $transactionJournal, ?TransactionGroup $transactionGroup)
|
||||
{
|
||||
Log::debug(sprintf('Created piggy bank event for piggy bank #%d with amount %s', $piggyBank->id, $amount));
|
||||
$this->piggyBank = $piggyBank;
|
||||
$this->transactionJournal = $transactionJournal;
|
||||
$this->transactionGroup = $transactionGroup;
|
||||
$this->amount = $amount;
|
||||
}
|
||||
}
|
@ -23,6 +23,7 @@ declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Factory;
|
||||
|
||||
use FireflyIII\Events\ChangedPiggyBankAmount;
|
||||
use FireflyIII\Models\PiggyBank;
|
||||
use FireflyIII\Models\PiggyBankEvent;
|
||||
use FireflyIII\Models\TransactionJournal;
|
||||
@ -40,22 +41,20 @@ class PiggyBankEventFactory
|
||||
/**
|
||||
* @param TransactionJournal $journal
|
||||
* @param PiggyBank|null $piggyBank
|
||||
*
|
||||
* @return PiggyBankEvent|null
|
||||
*/
|
||||
public function create(TransactionJournal $journal, ?PiggyBank $piggyBank): ?PiggyBankEvent
|
||||
public function create(TransactionJournal $journal, ?PiggyBank $piggyBank): void
|
||||
{
|
||||
Log::debug(sprintf('Now in PiggyBankEventCreate for a %s', $journal->transactionType->type));
|
||||
if (null === $piggyBank) {
|
||||
Log::debug('Piggy bank is null');
|
||||
|
||||
return null;
|
||||
return;
|
||||
}
|
||||
|
||||
if (TransactionType::TRANSFER !== $journal->transactionType->type) {
|
||||
Log::info(sprintf('Will not connect %s #%d to a piggy bank.', $journal->transactionType->type, $journal->id));
|
||||
|
||||
return null;
|
||||
return;
|
||||
}
|
||||
|
||||
/** @var PiggyBankRepositoryInterface $piggyRepos */
|
||||
@ -66,20 +65,16 @@ class PiggyBankEventFactory
|
||||
if (null === $repetition) {
|
||||
Log::error(sprintf('No piggy bank repetition on %s!', $journal->date->format('Y-m-d')));
|
||||
|
||||
return null;
|
||||
return;
|
||||
}
|
||||
Log::debug('Found repetition');
|
||||
$amount = $piggyRepos->getExactAmount($piggyBank, $repetition, $journal);
|
||||
if (0 === bccomp($amount, '0')) {
|
||||
Log::debug('Amount is zero, will not create event.');
|
||||
|
||||
return null;
|
||||
return;
|
||||
}
|
||||
|
||||
$piggyRepos->addAmountToRepetition($repetition, $amount);
|
||||
$event = $piggyRepos->createEventWithJournal($piggyBank, $amount, $journal);
|
||||
Log::debug(sprintf('Created piggy bank event #%d', $event->id));
|
||||
|
||||
return $event;
|
||||
// amount can be negative here
|
||||
$piggyRepos->addAmountToRepetition($repetition, $amount, $journal);
|
||||
}
|
||||
}
|
||||
|
@ -81,8 +81,8 @@ class TagFactory
|
||||
public function create(array $data): ?Tag
|
||||
{
|
||||
$zoomLevel = 0 === (int) $data['zoom_level'] ? null : (int) $data['zoom_level'];
|
||||
$latitude = 0.0 === (float) $data['latitude'] ? null : (float) $data['latitude'];
|
||||
$longitude = 0.0 === (float) $data['longitude'] ? null : (float) $data['longitude'];
|
||||
$latitude = 0.0 === (float) $data['latitude'] ? null : (float) $data['latitude']; // intentional float
|
||||
$longitude = 0.0 === (float) $data['longitude'] ? null : (float) $data['longitude']; // intentional float
|
||||
$array = [
|
||||
'user_id' => $this->user->id,
|
||||
'tag' => trim($data['tag']),
|
||||
|
@ -92,7 +92,7 @@ class TransactionJournalFactory
|
||||
/**
|
||||
* Store a new (set of) transaction journals.
|
||||
*
|
||||
* @param array $data
|
||||
* @param array $data
|
||||
*
|
||||
* @return Collection
|
||||
* @throws DuplicateTransactionException
|
||||
@ -143,7 +143,7 @@ class TransactionJournalFactory
|
||||
}
|
||||
|
||||
/**
|
||||
* @param NullArrayObject $row
|
||||
* @param NullArrayObject $row
|
||||
*
|
||||
* @return TransactionJournal|null
|
||||
* @throws DuplicateTransactionException
|
||||
@ -160,11 +160,11 @@ class TransactionJournalFactory
|
||||
$type = $this->typeRepository->findTransactionType(null, $row['type']);
|
||||
$carbon = $row['date'] ?? today(config('app.timezone'));
|
||||
$order = $row['order'] ?? 0;
|
||||
$currency = $this->currencyRepository->findCurrency((int) $row['currency_id'], $row['currency_code']);
|
||||
$currency = $this->currencyRepository->findCurrency((int)$row['currency_id'], $row['currency_code']);
|
||||
$foreignCurrency = $this->currencyRepository->findCurrencyNull($row['foreign_currency_id'], $row['foreign_currency_code']);
|
||||
$bill = $this->billRepository->findBill((int) $row['bill_id'], $row['bill_name']);
|
||||
$bill = $this->billRepository->findBill((int)$row['bill_id'], $row['bill_name']);
|
||||
$billId = TransactionType::WITHDRAWAL === $type->type && null !== $bill ? $bill->id : null;
|
||||
$description = (string) $row['description'];
|
||||
$description = (string)$row['description'];
|
||||
|
||||
/** Manipulate basic fields */
|
||||
$carbon->setTimezone(config('app.timezone'));
|
||||
@ -237,7 +237,7 @@ class TransactionJournalFactory
|
||||
$transactionFactory->setForeignCurrency($foreignCurrency);
|
||||
$transactionFactory->setReconciled($row['reconciled'] ?? false);
|
||||
try {
|
||||
$negative = $transactionFactory->createNegative((string) $row['amount'], (string) $row['foreign_amount']);
|
||||
$negative = $transactionFactory->createNegative((string)$row['amount'], (string)$row['foreign_amount']);
|
||||
} catch (FireflyException $e) {
|
||||
Log::error('Exception creating negative transaction.');
|
||||
Log::error($e->getMessage());
|
||||
@ -256,7 +256,7 @@ class TransactionJournalFactory
|
||||
$transactionFactory->setForeignCurrency($foreignCurrency);
|
||||
$transactionFactory->setReconciled($row['reconciled'] ?? false);
|
||||
try {
|
||||
$transactionFactory->createPositive((string) $row['amount'], (string) $row['foreign_amount']);
|
||||
$transactionFactory->createPositive((string)$row['amount'], (string)$row['foreign_amount']);
|
||||
} catch (FireflyException $e) {
|
||||
Log::error('Exception creating positive transaction.');
|
||||
Log::error($e->getMessage());
|
||||
@ -294,7 +294,7 @@ class TransactionJournalFactory
|
||||
}
|
||||
|
||||
/**
|
||||
* @param NullArrayObject $row
|
||||
* @param NullArrayObject $row
|
||||
*
|
||||
* @return string
|
||||
* @throws JsonException
|
||||
@ -306,10 +306,8 @@ class TransactionJournalFactory
|
||||
unset($dataRow['import_hash_v2'], $dataRow['original_source']);
|
||||
$json = json_encode($dataRow, JSON_THROW_ON_ERROR);
|
||||
if (false === $json) {
|
||||
|
||||
$json = json_encode((string) microtime(), JSON_THROW_ON_ERROR);
|
||||
$json = json_encode((string)microtime(), JSON_THROW_ON_ERROR);
|
||||
Log::error(sprintf('Could not hash the original row! %s', json_last_error_msg()), $dataRow);
|
||||
|
||||
}
|
||||
$hash = hash('sha256', $json);
|
||||
Log::debug(sprintf('The hash is: %s', $hash), $dataRow);
|
||||
@ -320,7 +318,7 @@ class TransactionJournalFactory
|
||||
/**
|
||||
* If this transaction already exists, throw an error.
|
||||
*
|
||||
* @param string $hash
|
||||
* @param string $hash
|
||||
*
|
||||
* @throws DuplicateTransactionException
|
||||
* @throws JsonException
|
||||
@ -353,7 +351,7 @@ class TransactionJournalFactory
|
||||
}
|
||||
|
||||
/**
|
||||
* @param NullArrayObject $data
|
||||
* @param NullArrayObject $data
|
||||
*
|
||||
* @throws FireflyException
|
||||
*/
|
||||
@ -366,10 +364,10 @@ class TransactionJournalFactory
|
||||
|
||||
// validate source account.
|
||||
$array = [
|
||||
'id' => $data['source_id'] ? (int) $data['source_id'] : null,
|
||||
'name' => $data['source_name'] ? (string) $data['source_name'] : null,
|
||||
'iban' => $data['source_iban'] ? (string) $data['source_iban'] : null,
|
||||
'number' => $data['source_number'] ? (string) $data['source_number'] : null,
|
||||
'id' => $data['source_id'] ? (int)$data['source_id'] : null,
|
||||
'name' => $data['source_name'] ? (string)$data['source_name'] : null,
|
||||
'iban' => $data['source_iban'] ? (string)$data['source_iban'] : null,
|
||||
'number' => $data['source_number'] ? (string)$data['source_number'] : null,
|
||||
];
|
||||
$validSource = $this->accountValidator->validateSource($array);
|
||||
|
||||
@ -381,10 +379,10 @@ class TransactionJournalFactory
|
||||
|
||||
// validate destination account
|
||||
$array = [
|
||||
'id' => $data['destination_id'] ? (int) $data['destination_id'] : null,
|
||||
'name' => $data['destination_name'] ? (string) $data['destination_name'] : null,
|
||||
'iban' => $data['destination_iban'] ? (string) $data['destination_iban'] : null,
|
||||
'number' => $data['destination_number'] ? (string) $data['destination_number'] : null,
|
||||
'id' => $data['destination_id'] ? (int)$data['destination_id'] : null,
|
||||
'name' => $data['destination_name'] ? (string)$data['destination_name'] : null,
|
||||
'iban' => $data['destination_iban'] ? (string)$data['destination_iban'] : null,
|
||||
'number' => $data['destination_number'] ? (string)$data['destination_number'] : null,
|
||||
];
|
||||
|
||||
$validDestination = $this->accountValidator->validateDestination($array);
|
||||
@ -395,10 +393,10 @@ class TransactionJournalFactory
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $type
|
||||
* @param TransactionCurrency|null $currency
|
||||
* @param Account $source
|
||||
* @param Account $destination
|
||||
* @param string $type
|
||||
* @param TransactionCurrency|null $currency
|
||||
* @param Account $source
|
||||
* @param Account $destination
|
||||
*
|
||||
* @return TransactionCurrency
|
||||
*/
|
||||
@ -413,8 +411,8 @@ class TransactionJournalFactory
|
||||
}
|
||||
|
||||
/**
|
||||
* @param TransactionCurrency|null $currency
|
||||
* @param Account $account
|
||||
* @param TransactionCurrency|null $currency
|
||||
* @param Account $account
|
||||
*
|
||||
* @return TransactionCurrency
|
||||
* @throws FireflyException
|
||||
@ -437,8 +435,8 @@ class TransactionJournalFactory
|
||||
/**
|
||||
* Set foreign currency to NULL if it's the same as the normal currency:
|
||||
*
|
||||
* @param TransactionCurrency|null $currency
|
||||
* @param TransactionCurrency|null $foreignCurrency
|
||||
* @param TransactionCurrency|null $currency
|
||||
* @param TransactionCurrency|null $foreignCurrency
|
||||
*
|
||||
* @return TransactionCurrency|null
|
||||
*/
|
||||
@ -455,9 +453,9 @@ class TransactionJournalFactory
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $type
|
||||
* @param TransactionCurrency|null $foreignCurrency
|
||||
* @param Account $destination
|
||||
* @param string $type
|
||||
* @param TransactionCurrency|null $foreignCurrency
|
||||
* @param Account $destination
|
||||
*
|
||||
* @return TransactionCurrency|null
|
||||
*/
|
||||
@ -471,7 +469,7 @@ class TransactionJournalFactory
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $description
|
||||
* @param string $description
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
@ -486,7 +484,7 @@ class TransactionJournalFactory
|
||||
* Force the deletion of an entire set of transaction journals and their meta object in case of
|
||||
* an error creating a group.
|
||||
*
|
||||
* @param Collection $collection
|
||||
* @param Collection $collection
|
||||
*/
|
||||
private function forceDeleteOnError(Collection $collection): void
|
||||
{
|
||||
@ -500,7 +498,7 @@ class TransactionJournalFactory
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Transaction $transaction
|
||||
* @param Transaction $transaction
|
||||
*/
|
||||
private function forceTrDelete(Transaction $transaction): void
|
||||
{
|
||||
@ -516,8 +514,8 @@ class TransactionJournalFactory
|
||||
/**
|
||||
* Link a piggy bank to this journal.
|
||||
*
|
||||
* @param TransactionJournal $journal
|
||||
* @param NullArrayObject $data
|
||||
* @param TransactionJournal $journal
|
||||
* @param NullArrayObject $data
|
||||
*/
|
||||
private function storePiggyEvent(TransactionJournal $journal, NullArrayObject $data): void
|
||||
{
|
||||
@ -528,7 +526,7 @@ class TransactionJournalFactory
|
||||
return;
|
||||
}
|
||||
|
||||
$piggyBank = $this->piggyRepository->findPiggyBank((int) $data['piggy_bank_id'], $data['piggy_bank_name']);
|
||||
$piggyBank = $this->piggyRepository->findPiggyBank((int)$data['piggy_bank_id'], $data['piggy_bank_name']);
|
||||
|
||||
if (null !== $piggyBank) {
|
||||
$this->piggyEventFactory->create($journal, $piggyBank);
|
||||
@ -540,8 +538,8 @@ class TransactionJournalFactory
|
||||
}
|
||||
|
||||
/**
|
||||
* @param TransactionJournal $journal
|
||||
* @param NullArrayObject $transaction
|
||||
* @param TransactionJournal $journal
|
||||
* @param NullArrayObject $transaction
|
||||
*/
|
||||
private function storeMetaFields(TransactionJournal $journal, NullArrayObject $transaction): void
|
||||
{
|
||||
@ -551,16 +549,16 @@ class TransactionJournalFactory
|
||||
}
|
||||
|
||||
/**
|
||||
* @param TransactionJournal $journal
|
||||
* @param NullArrayObject $data
|
||||
* @param string $field
|
||||
* @param TransactionJournal $journal
|
||||
* @param NullArrayObject $data
|
||||
* @param string $field
|
||||
*/
|
||||
protected function storeMeta(TransactionJournal $journal, NullArrayObject $data, string $field): void
|
||||
{
|
||||
$set = [
|
||||
'journal' => $journal,
|
||||
'name' => $field,
|
||||
'data' => (string) ($data[$field] ?? ''),
|
||||
'data' => (string)($data[$field] ?? ''),
|
||||
];
|
||||
|
||||
//Log::debug(sprintf('Going to store meta-field "%s", with value "%s".', $set['name'], $set['data']));
|
||||
@ -571,7 +569,7 @@ class TransactionJournalFactory
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bool $errorOnHash
|
||||
* @param bool $errorOnHash
|
||||
*/
|
||||
public function setErrorOnHash(bool $errorOnHash): void
|
||||
{
|
||||
@ -584,7 +582,7 @@ class TransactionJournalFactory
|
||||
/**
|
||||
* Set the user.
|
||||
*
|
||||
* @param User $user
|
||||
* @param User $user
|
||||
*/
|
||||
public function setUser(User $user): void
|
||||
{
|
||||
|
@ -59,7 +59,7 @@ class ChartJsGenerator implements GeneratorInterface
|
||||
$index = 0;
|
||||
foreach ($data as $key => $valueArray) {
|
||||
// make larger than 0
|
||||
$chartData['datasets'][0]['data'][] = (float) app('steam')->positive((string) $valueArray['amount']);
|
||||
$chartData['datasets'][0]['data'][] = app('steam')->positive((string) $valueArray['amount']);
|
||||
$chartData['datasets'][0]['backgroundColor'][] = ChartColour::getColour($index);
|
||||
$chartData['datasets'][0]['currency_symbol'][] = $valueArray['currency_symbol'];
|
||||
$chartData['labels'][] = $key;
|
||||
@ -174,7 +174,7 @@ class ChartJsGenerator implements GeneratorInterface
|
||||
$index = 0;
|
||||
foreach ($data as $key => $value) {
|
||||
// make larger than 0
|
||||
$chartData['datasets'][0]['data'][] = (float) app('steam')->positive((string) $value);
|
||||
$chartData['datasets'][0]['data'][] = app('steam')->positive((string) $value);
|
||||
$chartData['datasets'][0]['backgroundColor'][] = ChartColour::getColour($index);
|
||||
|
||||
$chartData['labels'][] = $key;
|
||||
|
70
app/Handlers/Events/PiggyBankEventHandler.php
Normal file
70
app/Handlers/Events/PiggyBankEventHandler.php
Normal file
@ -0,0 +1,70 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
/*
|
||||
* PiggyBankEventHandler.php
|
||||
* Copyright (c) 2022 james@firefly-iii.org
|
||||
*
|
||||
* This file is part of Firefly III (https://github.com/firefly-iii).
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
namespace FireflyIII\Handlers\Events;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use FireflyIII\Events\ChangedPiggyBankAmount;
|
||||
use FireflyIII\Models\PiggyBankEvent;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
|
||||
/**
|
||||
* Class PiggyBankEventHandler
|
||||
*/
|
||||
class PiggyBankEventHandler
|
||||
{
|
||||
/**
|
||||
* @param ChangedPiggyBankAmount $event
|
||||
* @return void
|
||||
*/
|
||||
public function changePiggyAmount(ChangedPiggyBankAmount $event): void
|
||||
{
|
||||
// find journal if group is present.
|
||||
$journal = $event->transactionJournal;
|
||||
if (null !== $event->transactionGroup) {
|
||||
$journal = $event->transactionGroup->transactionJournals()->first();
|
||||
}
|
||||
$date = $journal?->date ?? Carbon::now();
|
||||
|
||||
// sanity check: event must not already exist for this journal and piggy bank.
|
||||
if (null !== $journal) {
|
||||
$exists = PiggyBankEvent::where('piggy_bank_id', $event->piggyBank->id)
|
||||
->where('transaction_journal_id', $journal->id)
|
||||
->exists();
|
||||
if($exists) {
|
||||
Log::warning('Already have event for this journal and piggy, will not create another.');
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
PiggyBankEvent::create(
|
||||
[
|
||||
'piggy_bank_id' => $event->piggyBank->id,
|
||||
'transaction_journal_id' => $journal?->id,
|
||||
'date' => $date->format('Y-m-d'),
|
||||
'amount' => $event->amount,
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
}
|
@ -72,6 +72,7 @@ trait AttachmentCollection
|
||||
Log::debug('Add filter on attachment ID.');
|
||||
$this->joinAttachmentTables();
|
||||
$this->query->whereNotNull('attachments.attachable_id');
|
||||
$this->query->whereNull('attachments.deleted_at');
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
@ -699,4 +699,17 @@ trait MetaCollection
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function setSepaCT(string $sepaCT): GroupCollectorInterface
|
||||
{
|
||||
$this->joinMetaDataTables();
|
||||
$this->query->where('journal_meta.name', '=', 'sepa_ct_id');
|
||||
$this->query->where('journal_meta.data', '=', sprintf('%s', json_encode($sepaCT)));
|
||||
$this->query->whereNull('journal_meta.deleted_at');
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
|
@ -135,6 +135,7 @@ class EditController extends Controller
|
||||
|
||||
// code to handle active-checkboxes
|
||||
$hasOldInput = null !== $request->old('_token');
|
||||
$virtualBalance = null === $account->virtual_balance ? '0' : $account->virtual_balance;
|
||||
$preFilled = [
|
||||
'account_number' => $repository->getMetaValue($account, 'account_number'),
|
||||
'account_role' => $repository->getMetaValue($account, 'account_role'),
|
||||
@ -143,9 +144,9 @@ class EditController extends Controller
|
||||
'BIC' => $repository->getMetaValue($account, 'BIC'),
|
||||
'opening_balance_date' => $openingBalanceDate,
|
||||
'liability_type_id' => $account->account_type_id,
|
||||
'opening_balance' => number_format((float) $openingBalanceAmount, $currency->decimal_places, '.', ''),
|
||||
'opening_balance' => app('steam')->bcround($openingBalanceAmount, $currency->decimal_places),
|
||||
'liability_direction' => $this->repository->getMetaValue($account, 'liability_direction'),
|
||||
'virtual_balance' => number_format((float) $account->virtual_balance, $currency->decimal_places, '.', ''),
|
||||
'virtual_balance' => app('steam')->bcround($virtualBalance, $currency->decimal_places),
|
||||
'currency_id' => $currency->id,
|
||||
'include_net_worth' => $includeNetWorth,
|
||||
'interest' => $repository->getMetaValue($account, 'interest'),
|
||||
|
@ -108,7 +108,7 @@ class IndexController extends Controller
|
||||
$account->startBalance = $this->isInArray($startBalances, $account->id);
|
||||
$account->endBalance = $this->isInArray($endBalances, $account->id);
|
||||
$account->difference = bcsub($account->endBalance, $account->startBalance);
|
||||
$account->interest = number_format((float) $this->repository->getMetaValue($account, 'interest'), 4, '.', '');
|
||||
$account->interest = app('steam')->bcround($this->repository->getMetaValue($account, 'interest'), 4);
|
||||
$account->interestPeriod = (string) trans(sprintf('firefly.interest_calc_%s', $this->repository->getMetaValue($account, 'interest_period')));
|
||||
$account->accountTypeString = (string) trans(sprintf('firefly.account_type_%s', $account->accountType->type));
|
||||
$account->current_debt = '0';
|
||||
@ -167,14 +167,19 @@ class IndexController extends Controller
|
||||
$endBalances = app('steam')->balancesByAccounts($accounts, $end);
|
||||
$activities = app('steam')->getLastActivities($ids);
|
||||
|
||||
|
||||
$accounts->each(
|
||||
function (Account $account) use ($activities, $startBalances, $endBalances) {
|
||||
|
||||
$interest = (string)$this->repository->getMetaValue($account, 'interest');
|
||||
$interest = '' === $interest ? '0' : $interest;
|
||||
|
||||
// See reference nr. 68
|
||||
$account->lastActivityDate = $this->isInArrayDate($activities, $account->id);
|
||||
$account->startBalance = $this->isInArray($startBalances, $account->id);
|
||||
$account->endBalance = $this->isInArray($endBalances, $account->id);
|
||||
$account->difference = bcsub($account->endBalance, $account->startBalance);
|
||||
$account->interest = number_format((float) $this->repository->getMetaValue($account, 'interest'), 4, '.', '');
|
||||
$account->interest = app('steam')->bcround($interest, 4);
|
||||
$account->interestPeriod = (string) trans(
|
||||
sprintf('firefly.interest_calc_%s', $this->repository->getMetaValue($account, 'interest_period'))
|
||||
);
|
||||
|
@ -128,8 +128,8 @@ class ReconcileController extends Controller
|
||||
|
||||
$startDate = clone $start;
|
||||
$startDate->subDay();
|
||||
$startBalance = number_format((float) app('steam')->balance($account, $startDate), $currency->decimal_places, '.', '');
|
||||
$endBalance = number_format((float) app('steam')->balance($account, $end), $currency->decimal_places, '.', '');
|
||||
$startBalance = app('steam')->bcround(app('steam')->balance($account, $startDate), $currency->decimal_places);
|
||||
$endBalance = app('steam')->bcround( app('steam')->balance($account, $end), $currency->decimal_places);
|
||||
$subTitleIcon = config(sprintf('firefly.subIconsByIdentifier.%s', $account->accountType->type));
|
||||
$subTitle = (string) trans('firefly.reconcile_account', ['account' => $account->name]);
|
||||
|
||||
|
@ -148,7 +148,7 @@ class RegisterController extends Controller
|
||||
$allowRegistration = $this->allowedToRegister();
|
||||
|
||||
if (false === $allowRegistration) {
|
||||
$message = 'Registration is currently not available.';
|
||||
$message = 'Registration is currently not available. If you are the administrator, you can enable this in the administration.';
|
||||
|
||||
return view('error', compact('message'));
|
||||
}
|
||||
|
@ -89,8 +89,8 @@ class EditController extends Controller
|
||||
}
|
||||
|
||||
$currency = app('amount')->getDefaultCurrency();
|
||||
$bill->amount_min = round((float) $bill->amount_min, $currency->decimal_places);
|
||||
$bill->amount_max = round((float) $bill->amount_max, $currency->decimal_places);
|
||||
$bill->amount_min = app('steam')->bcround($bill->amount_min, $currency->decimal_places);
|
||||
$bill->amount_max = app('steam')->bcround($bill->amount_max, $currency->decimal_places);
|
||||
$rules = $this->repository->getRulesForBill($bill);
|
||||
$defaultCurrency = app('amount')->getDefaultCurrency();
|
||||
|
||||
|
@ -162,7 +162,7 @@ class AvailableBudgetController extends Controller
|
||||
*/
|
||||
public function edit(AvailableBudget $availableBudget, Carbon $start, Carbon $end)
|
||||
{
|
||||
$availableBudget->amount = number_format((float) $availableBudget->amount, $availableBudget->transactionCurrency->decimal_places, '.', '');
|
||||
$availableBudget->amount = app('steam')->bcround($availableBudget->amount, $availableBudget->transactionCurrency->decimal_places);
|
||||
|
||||
return view('budgets.available-budgets.edit', compact('availableBudget', 'start', 'end'));
|
||||
}
|
||||
|
@ -65,7 +65,7 @@ class BudgetLimitController extends Controller
|
||||
parent::__construct();
|
||||
$this->middleware(
|
||||
function ($request, $next) {
|
||||
app('view')->share('title', (string) trans('firefly.budgets'));
|
||||
app('view')->share('title', (string)trans('firefly.budgets'));
|
||||
app('view')->share('mainTitleIcon', 'fa-pie-chart');
|
||||
$this->repository = app(BudgetRepositoryInterface::class);
|
||||
$this->opsRepository = app(OperationsRepositoryInterface::class);
|
||||
@ -78,9 +78,9 @@ class BudgetLimitController extends Controller
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Budget $budget
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
* @param Budget $budget
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
*
|
||||
* @return Factory|View
|
||||
*/
|
||||
@ -107,8 +107,8 @@ class BudgetLimitController extends Controller
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Request $request
|
||||
* @param BudgetLimit $budgetLimit
|
||||
* @param Request $request
|
||||
* @param BudgetLimit $budgetLimit
|
||||
*
|
||||
* @return RedirectResponse|Redirector
|
||||
*/
|
||||
@ -121,7 +121,7 @@ class BudgetLimitController extends Controller
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Request $request
|
||||
* @param Request $request
|
||||
*
|
||||
* @return JsonResponse
|
||||
* @throws FireflyException
|
||||
@ -130,14 +130,14 @@ class BudgetLimitController extends Controller
|
||||
{
|
||||
Log::debug('Going to store new budget-limit.', $request->all());
|
||||
// first search for existing one and update it if necessary.
|
||||
$currency = $this->currencyRepos->find((int) $request->get('transaction_currency_id'));
|
||||
$budget = $this->repository->find((int) $request->get('budget_id'));
|
||||
$currency = $this->currencyRepos->find((int)$request->get('transaction_currency_id'));
|
||||
$budget = $this->repository->find((int)$request->get('budget_id'));
|
||||
if (null === $currency || null === $budget) {
|
||||
throw new FireflyException('No valid currency or budget.');
|
||||
}
|
||||
$start = Carbon::createFromFormat('Y-m-d', $request->get('start'));
|
||||
$end = Carbon::createFromFormat('Y-m-d', $request->get('end'));
|
||||
$amount = (string) $request->get('amount');
|
||||
$amount = (string)$request->get('amount');
|
||||
$start->startOfDay();
|
||||
$end->startOfDay();
|
||||
|
||||
@ -150,17 +150,17 @@ class BudgetLimitController extends Controller
|
||||
$limit = $this->blRepository->find($budget, $currency, $start, $end);
|
||||
|
||||
// sanity check on amount:
|
||||
if ((float) $amount === 0.0) {
|
||||
if (0 === bccomp($amount, '0')) {
|
||||
if (null !== $limit) {
|
||||
$this->blRepository->destroyBudgetLimit($limit);
|
||||
}
|
||||
// return empty=ish array:
|
||||
return response()->json([]);
|
||||
}
|
||||
if ((int) $amount > 268435456) {
|
||||
if ((int)$amount > 268435456) { // intentional cast to integer
|
||||
$amount = '268435456';
|
||||
}
|
||||
if((float) $amount < 0.0) {
|
||||
if (-1 === bccomp($amount, '0')) {
|
||||
$amount = bcmul($amount, '-1');
|
||||
}
|
||||
|
||||
@ -172,7 +172,7 @@ class BudgetLimitController extends Controller
|
||||
$limit = $this->blRepository->store(
|
||||
[
|
||||
'budget_id' => $request->get('budget_id'),
|
||||
'currency_id' => (int) $request->get('transaction_currency_id'),
|
||||
'currency_id' => (int)$request->get('transaction_currency_id'),
|
||||
'start_date' => $start,
|
||||
'end_date' => $end,
|
||||
'amount' => $amount,
|
||||
@ -187,7 +187,7 @@ class BudgetLimitController extends Controller
|
||||
$array['spent'] = $spentArr[$currency->id]['sum'] ?? '0';
|
||||
$array['left_formatted'] = app('amount')->formatAnything($limit->transactionCurrency, bcadd($array['spent'], $array['amount']));
|
||||
$array['amount_formatted'] = app('amount')->formatAnything($limit->transactionCurrency, $limit['amount']);
|
||||
$array['days_left'] = (string) $this->activeDaysLeft($start, $end);
|
||||
$array['days_left'] = (string)$this->activeDaysLeft($start, $end);
|
||||
// left per day:
|
||||
$array['left_per_day'] = bcdiv(bcadd($array['spent'], $array['amount']), $array['days_left']);
|
||||
|
||||
@ -201,20 +201,20 @@ class BudgetLimitController extends Controller
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Request $request
|
||||
* @param BudgetLimit $budgetLimit
|
||||
* @param Request $request
|
||||
* @param BudgetLimit $budgetLimit
|
||||
*
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function update(Request $request, BudgetLimit $budgetLimit): JsonResponse
|
||||
{
|
||||
$amount = (string) $request->get('amount');
|
||||
$amount = (string)$request->get('amount');
|
||||
if ('' === $amount) {
|
||||
$amount = '0';
|
||||
}
|
||||
|
||||
// sanity check on amount:
|
||||
if ((float) $amount === 0.0) {
|
||||
if (0 === bccomp($amount, '0')) {
|
||||
$budgetId = $budgetLimit->budget_id;
|
||||
$currency = $budgetLimit->transactionCurrency;
|
||||
$this->blRepository->destroyBudgetLimit($budgetLimit);
|
||||
@ -226,10 +226,10 @@ class BudgetLimitController extends Controller
|
||||
];
|
||||
return response()->json($array);
|
||||
}
|
||||
if ((int) $amount > 268435456) { // 268 million
|
||||
if ((int)$amount > 268435456) { // 268 million, intentional integer
|
||||
$amount = '268435456';
|
||||
}
|
||||
if((float) $amount < 0.0) {
|
||||
if (-1 === bccomp($amount, '0')) {
|
||||
$amount = bcmul($amount, '-1');
|
||||
}
|
||||
|
||||
@ -246,12 +246,12 @@ class BudgetLimitController extends Controller
|
||||
$array['spent'] = $spentArr[$budgetLimit->transactionCurrency->id]['sum'] ?? '0';
|
||||
$array['left_formatted'] = app('amount')->formatAnything($limit->transactionCurrency, bcadd($array['spent'], $array['amount']));
|
||||
$array['amount_formatted'] = app('amount')->formatAnything($limit->transactionCurrency, $limit['amount']);
|
||||
$array['days_left'] = (string) $this->activeDaysLeft($limit->start_date, $limit->end_date);
|
||||
$array['days_left'] = (string)$this->activeDaysLeft($limit->start_date, $limit->end_date);
|
||||
// left per day:
|
||||
$array['left_per_day'] = bcdiv(bcadd($array['spent'], $array['amount']), $array['days_left']);
|
||||
|
||||
// left per day formatted.
|
||||
$array['amount'] = number_format((float) $limit['amount'], $limit->transactionCurrency->decimal_places, '.', '');
|
||||
$array['amount'] = app('steam')->bcround($limit['amount'], $limit->transactionCurrency->decimal_places);
|
||||
$array['left_per_day_formatted'] = app('amount')->formatAnything($limit->transactionCurrency, $array['left_per_day']);
|
||||
|
||||
return response()->json($array);
|
||||
|
@ -56,7 +56,7 @@ class EditController extends Controller
|
||||
|
||||
$this->middleware(
|
||||
function ($request, $next) {
|
||||
app('view')->share('title', (string) trans('firefly.budgets'));
|
||||
app('view')->share('title', (string)trans('firefly.budgets'));
|
||||
app('view')->share('mainTitleIcon', 'fa-pie-chart');
|
||||
$this->repository = app(BudgetRepositoryInterface::class);
|
||||
$this->attachments = app(AttachmentHelperInterface::class);
|
||||
@ -69,41 +69,41 @@ class EditController extends Controller
|
||||
/**
|
||||
* Budget edit form.
|
||||
*
|
||||
* @param Request $request
|
||||
* @param Budget $budget
|
||||
* @param Request $request
|
||||
* @param Budget $budget
|
||||
*
|
||||
* @return Factory|View
|
||||
*/
|
||||
public function edit(Request $request, Budget $budget)
|
||||
{
|
||||
$subTitle = (string) trans('firefly.edit_budget', ['name' => $budget->name]);
|
||||
$subTitle = (string)trans('firefly.edit_budget', ['name' => $budget->name]);
|
||||
$autoBudget = $this->repository->getAutoBudget($budget);
|
||||
|
||||
// auto budget types
|
||||
$autoBudgetTypes = [
|
||||
0 => (string) trans('firefly.auto_budget_none'),
|
||||
AutoBudget::AUTO_BUDGET_RESET => (string) trans('firefly.auto_budget_reset'),
|
||||
AutoBudget::AUTO_BUDGET_ROLLOVER => (string) trans('firefly.auto_budget_rollover'),
|
||||
0 => (string)trans('firefly.auto_budget_none'),
|
||||
AutoBudget::AUTO_BUDGET_RESET => (string)trans('firefly.auto_budget_reset'),
|
||||
AutoBudget::AUTO_BUDGET_ROLLOVER => (string)trans('firefly.auto_budget_rollover'),
|
||||
];
|
||||
$autoBudgetPeriods = [
|
||||
'daily' => (string) trans('firefly.auto_budget_period_daily'),
|
||||
'weekly' => (string) trans('firefly.auto_budget_period_weekly'),
|
||||
'monthly' => (string) trans('firefly.auto_budget_period_monthly'),
|
||||
'quarterly' => (string) trans('firefly.auto_budget_period_quarterly'),
|
||||
'half_year' => (string) trans('firefly.auto_budget_period_half_year'),
|
||||
'yearly' => (string) trans('firefly.auto_budget_period_yearly'),
|
||||
'daily' => (string)trans('firefly.auto_budget_period_daily'),
|
||||
'weekly' => (string)trans('firefly.auto_budget_period_weekly'),
|
||||
'monthly' => (string)trans('firefly.auto_budget_period_monthly'),
|
||||
'quarterly' => (string)trans('firefly.auto_budget_period_quarterly'),
|
||||
'half_year' => (string)trans('firefly.auto_budget_period_half_year'),
|
||||
'yearly' => (string)trans('firefly.auto_budget_period_yearly'),
|
||||
];
|
||||
|
||||
// code to handle active-checkboxes
|
||||
$hasOldInput = null !== $request->old('_token');
|
||||
$currency = app('amount')->getDefaultCurrency();
|
||||
$preFilled = [
|
||||
'active' => $hasOldInput ? (bool) $request->old('active') : $budget->active,
|
||||
'auto_budget_currency_id' => $hasOldInput ? (int) $request->old('auto_budget_currency_id') : $currency->id,
|
||||
'active' => $hasOldInput ? (bool)$request->old('active') : $budget->active,
|
||||
'auto_budget_currency_id' => $hasOldInput ? (int)$request->old('auto_budget_currency_id') : $currency->id,
|
||||
];
|
||||
if ($autoBudget) {
|
||||
$amount = $hasOldInput ? $request->old('auto_budget_amount') : $autoBudget->amount;
|
||||
$preFilled['auto_budget_amount'] = number_format((float) $amount, $autoBudget->transactionCurrency->decimal_places, '.', '');
|
||||
$preFilled['auto_budget_amount'] = app('steam')->bcround($amount, $autoBudget->transactionCurrency->decimal_places);
|
||||
}
|
||||
|
||||
// put previous url in session if not redirect from store (not "return_to_edit").
|
||||
@ -119,8 +119,8 @@ class EditController extends Controller
|
||||
/**
|
||||
* Budget update routine.
|
||||
*
|
||||
* @param BudgetFormUpdateRequest $request
|
||||
* @param Budget $budget
|
||||
* @param BudgetFormUpdateRequest $request
|
||||
* @param Budget $budget
|
||||
*
|
||||
* @return RedirectResponse
|
||||
*/
|
||||
@ -129,7 +129,7 @@ class EditController extends Controller
|
||||
$data = $request->getBudgetData();
|
||||
$this->repository->update($budget, $data);
|
||||
|
||||
$request->session()->flash('success', (string) trans('firefly.updated_budget', ['name' => $budget->name]));
|
||||
$request->session()->flash('success', (string)trans('firefly.updated_budget', ['name' => $budget->name]));
|
||||
$this->repository->cleanupBudgets();
|
||||
app('preferences')->mark();
|
||||
|
||||
@ -141,19 +141,17 @@ class EditController extends Controller
|
||||
$this->attachments->saveAttachmentsForModel($budget, $files);
|
||||
}
|
||||
if (null !== $files && auth()->user()->hasRole('demo')) {
|
||||
session()->flash('info', (string) trans('firefly.no_att_demo_user'));
|
||||
session()->flash('info', (string)trans('firefly.no_att_demo_user'));
|
||||
}
|
||||
|
||||
if (count($this->attachments->getMessages()->get('attachments')) > 0) {
|
||||
$request->session()->flash('info', $this->attachments->getMessages()->get('attachments'));
|
||||
}
|
||||
|
||||
if (1 === (int) $request->get('return_to_edit')) {
|
||||
|
||||
if (1 === (int)$request->get('return_to_edit')) {
|
||||
$request->session()->put('budgets.edit.fromUpdate', true);
|
||||
|
||||
$redirect = redirect(route('budgets.edit', [$budget->id]))->withInput(['return_to_edit' => 1]);
|
||||
|
||||
}
|
||||
|
||||
return $redirect;
|
||||
|
@ -210,7 +210,7 @@ class IndexController extends Controller
|
||||
$currency = $limit->transactionCurrency ?? $defaultCurrency;
|
||||
$array['budgeted'][] = [
|
||||
'id' => $limit->id,
|
||||
'amount' => number_format((float) $limit->amount, $currency->decimal_places, '.', ''),
|
||||
'amount' => app('steam')->bcround($limit->amount, $currency->decimal_places),
|
||||
'start_date' => $limit->start_date->isoFormat($this->monthAndDayFormat),
|
||||
'end_date' => $limit->end_date->isoFormat($this->monthAndDayFormat),
|
||||
'in_range' => $limit->start_date->isSameDay($start) && $limit->end_date->isSameDay($end),
|
||||
|
@ -127,7 +127,7 @@ class AccountController extends Controller
|
||||
$tempData[] = [
|
||||
'name' => $accountNames[$accountId],
|
||||
'difference' => $diff,
|
||||
'diff_float' => (float) $diff,
|
||||
'diff_float' => (float) $diff, // intentional float
|
||||
'currency_id' => $currencyId,
|
||||
];
|
||||
}
|
||||
@ -492,7 +492,7 @@ class AccountController extends Controller
|
||||
$theDate = $current->format('Y-m-d');
|
||||
$balance = $range[$theDate] ?? $previous;
|
||||
$label = $current->isoFormat($format);
|
||||
$entries[$label] = (float) $balance;
|
||||
$entries[$label] = $balance;
|
||||
$previous = $balance;
|
||||
$current->addDay();
|
||||
}
|
||||
@ -502,7 +502,7 @@ class AccountController extends Controller
|
||||
case '1M':
|
||||
case '1Y':
|
||||
while ($end >= $current) {
|
||||
$balance = (float) app('steam')->balance($account, $current, $currency);
|
||||
$balance = app('steam')->balance($account, $current, $currency);
|
||||
$label = app('navigation')->periodShow($current, $step);
|
||||
$entries[$label] = $balance;
|
||||
$current = app('navigation')->addPeriod($current, $step, 0);
|
||||
@ -586,7 +586,7 @@ class AccountController extends Controller
|
||||
$tempData[] = [
|
||||
'name' => $accountNames[$accountId],
|
||||
'difference' => $diff,
|
||||
'diff_float' => (float) $diff,
|
||||
'diff_float' => (float) $diff, // intentional float
|
||||
'currency_id' => $currencyId,
|
||||
];
|
||||
}
|
||||
|
@ -483,13 +483,13 @@ class BudgetController extends Controller
|
||||
// get budget limit in this period for this currency.
|
||||
$limit = $this->blRepository->find($budget, $currency, $currentStart, $currentEnd);
|
||||
if (null !== $limit) {
|
||||
$chartData[1]['entries'][$title] = round((float) $limit->amount, $currency->decimal_places);
|
||||
$chartData[1]['entries'][$title] = app('steam')->bcround($limit->amount, $currency->decimal_places);
|
||||
}
|
||||
|
||||
// get spent amount in this period for this currency.
|
||||
$sum = $this->opsRepository->sumExpenses($currentStart, $currentEnd, $accounts, new Collection([$budget]), $currency);
|
||||
$amount = app('steam')->positive($sum[$currency->id]['sum'] ?? '0');
|
||||
$chartData[0]['entries'][$title] = round((float) $amount, $currency->decimal_places);
|
||||
$chartData[0]['entries'][$title] = app('steam')->bcround($amount, $currency->decimal_places);
|
||||
|
||||
$currentStart = clone $currentEnd;
|
||||
$currentStart->addDay()->startOfDay();
|
||||
@ -534,7 +534,7 @@ class BudgetController extends Controller
|
||||
$title = $currentStart->isoFormat($titleFormat);
|
||||
$sum = $this->nbRepository->sumExpenses($currentStart, $currentEnd, $accounts, $currency);
|
||||
$amount = app('steam')->positive($sum[$currency->id]['sum'] ?? '0');
|
||||
$chartData[$title] = round((float) $amount, $currency->decimal_places);
|
||||
$chartData[$title] = app('steam')->bcround($amount, $currency->decimal_places);
|
||||
$currentStart = app('navigation')->addPeriod($currentStart, $preferredRange, 0);
|
||||
}
|
||||
|
||||
|
@ -243,8 +243,8 @@ class ReportController extends Controller
|
||||
while ($currentStart <= $end) {
|
||||
$key = $currentStart->format($format);
|
||||
$title = $currentStart->isoFormat($titleFormat);
|
||||
$income['entries'][$title] = round((float) ($currency[$key]['earned'] ?? '0'), $currency['currency_decimal_places']);
|
||||
$expense['entries'][$title] = round((float) ($currency[$key]['spent'] ?? '0'), $currency['currency_decimal_places']);
|
||||
$income['entries'][$title] = app('steam')->bcround(($currency[$key]['earned'] ?? '0'), $currency['currency_decimal_places']);
|
||||
$expense['entries'][$title] = app('steam')->bcround(($currency[$key]['spent'] ?? '0'), $currency['currency_decimal_places']);
|
||||
$currentStart = app('navigation')->addPeriod($currentStart, $preferredRange, 0);
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,5 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* FrontpageController.php
|
||||
* Copyright (c) 2019 james@firefly-iii.org
|
||||
@ -37,7 +38,7 @@ class FrontpageController extends Controller
|
||||
/**
|
||||
* Piggy bank pie chart.
|
||||
*
|
||||
* @param PiggyBankRepositoryInterface $repository
|
||||
* @param PiggyBankRepositoryInterface $repository
|
||||
*
|
||||
* @return JsonResponse
|
||||
*/
|
||||
@ -51,7 +52,7 @@ class FrontpageController extends Controller
|
||||
if (1 === bccomp($amount, '0')) {
|
||||
// percentage!
|
||||
$pct = 0;
|
||||
if (0.0 !== (float) $piggyBank->targetamount) {
|
||||
if (0 !== bccomp($piggyBank->targetamount, '0')) {
|
||||
$pct = round(($amount / $piggyBank->targetamount) * 100);
|
||||
}
|
||||
|
||||
@ -70,12 +71,10 @@ class FrontpageController extends Controller
|
||||
if (!empty($info)) {
|
||||
try {
|
||||
$html = view('json.piggy-banks', compact('info'))->render();
|
||||
|
||||
} catch (Throwable $e) { // @phpstan-ignore-line
|
||||
Log::error(sprintf('Cannot render json.piggy-banks: %s', $e->getMessage()));
|
||||
$html = 'Could not render view.';
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return response()->json(['html' => $html]);
|
||||
|
@ -238,8 +238,8 @@ class ReconcileController extends Controller
|
||||
$startDate->subDay();
|
||||
|
||||
$currency = $this->accountRepos->getAccountCurrency($account) ?? app('amount')->getDefaultCurrency();
|
||||
$startBalance = round((float) app('steam')->balance($account, $startDate), $currency->decimal_places);
|
||||
$endBalance = round((float) app('steam')->balance($account, $end), $currency->decimal_places);
|
||||
$startBalance = app('steam')->bcround(app('steam')->balance($account, $startDate), $currency->decimal_places);
|
||||
$endBalance = app('steam')->bcround(app('steam')->balance($account, $end), $currency->decimal_places);
|
||||
|
||||
// get the transactions
|
||||
$selectionStart = clone $start;
|
||||
|
@ -78,7 +78,7 @@ class AmountController extends Controller
|
||||
$leftOnAccount = $this->piggyRepos->leftOnAccount($piggyBank, today(config('app.timezone')));
|
||||
$savedSoFar = $this->piggyRepos->getCurrentAmount($piggyBank);
|
||||
$maxAmount = $leftOnAccount;
|
||||
if (0.000 !== (float) $piggyBank->targetamount) {
|
||||
if (0 !== bccomp($piggyBank->targetamount,'0')) {
|
||||
$leftToSave = bcsub($piggyBank->targetamount, $savedSoFar);
|
||||
$maxAmount = min($leftOnAccount, $leftToSave);
|
||||
}
|
||||
@ -102,7 +102,7 @@ class AmountController extends Controller
|
||||
$savedSoFar = $this->piggyRepos->getCurrentAmount($piggyBank);
|
||||
$maxAmount = $leftOnAccount;
|
||||
|
||||
if (0.000 !== (float) $piggyBank->targetamount) {
|
||||
if (0 !== bccomp($piggyBank->targetamount,'0')) {
|
||||
$leftToSave = bcsub($piggyBank->targetamount, $savedSoFar);
|
||||
$maxAmount = min($leftOnAccount, $leftToSave);
|
||||
}
|
||||
@ -129,7 +129,6 @@ class AmountController extends Controller
|
||||
}
|
||||
if ($this->piggyRepos->canAddAmount($piggyBank, $amount)) {
|
||||
$this->piggyRepos->addAmount($piggyBank, $amount);
|
||||
$this->piggyRepos->createEvent($piggyBank, $amount);
|
||||
session()->flash(
|
||||
'success',
|
||||
(string) trans(
|
||||
@ -183,7 +182,7 @@ class AmountController extends Controller
|
||||
|
||||
return redirect(route('piggy-banks.index'));
|
||||
}
|
||||
$amount = number_format((float) $request->get('amount'), 12, '.', '');
|
||||
$amount = (string) $request->get('amount');
|
||||
|
||||
session()->flash(
|
||||
'error',
|
||||
|
@ -56,7 +56,7 @@ class EditController extends Controller
|
||||
|
||||
$this->middleware(
|
||||
function ($request, $next) {
|
||||
app('view')->share('title', (string) trans('firefly.piggyBanks'));
|
||||
app('view')->share('title', (string)trans('firefly.piggyBanks'));
|
||||
app('view')->share('mainTitleIcon', 'fa-bullseye');
|
||||
|
||||
$this->attachments = app(AttachmentHelperInterface::class);
|
||||
@ -70,13 +70,13 @@ class EditController extends Controller
|
||||
/**
|
||||
* Edit a piggy bank.
|
||||
*
|
||||
* @param PiggyBank $piggyBank
|
||||
* @param PiggyBank $piggyBank
|
||||
*
|
||||
* @return Factory|View
|
||||
*/
|
||||
public function edit(PiggyBank $piggyBank)
|
||||
{
|
||||
$subTitle = (string) trans('firefly.update_piggy_title', ['name' => $piggyBank->name]);
|
||||
$subTitle = (string)trans('firefly.update_piggy_title', ['name' => $piggyBank->name]);
|
||||
$subTitleIcon = 'fa-pencil';
|
||||
$note = $piggyBank->notes()->first();
|
||||
// Flash some data to fill the form.
|
||||
@ -87,15 +87,16 @@ class EditController extends Controller
|
||||
$currency = Amount::getDefaultCurrency();
|
||||
}
|
||||
|
||||
$preFilled = ['name' => $piggyBank->name,
|
||||
'account_id' => $piggyBank->account_id,
|
||||
'targetamount' => number_format((float) $piggyBank->targetamount, $currency->decimal_places, '.', ''),
|
||||
'targetdate' => $targetDate,
|
||||
'startdate' => $startDate,
|
||||
'object_group' => $piggyBank->objectGroups->first() ? $piggyBank->objectGroups->first()->title : '',
|
||||
'notes' => null === $note ? '' : $note->text,
|
||||
$preFilled = [
|
||||
'name' => $piggyBank->name,
|
||||
'account_id' => $piggyBank->account_id,
|
||||
'targetamount' => app('steam')->bcround($piggyBank->targetamount, $currency->decimal_places),
|
||||
'targetdate' => $targetDate,
|
||||
'startdate' => $startDate,
|
||||
'object_group' => $piggyBank->objectGroups->first() ? $piggyBank->objectGroups->first()->title : '',
|
||||
'notes' => null === $note ? '' : $note->text,
|
||||
];
|
||||
if (0.0 === (float) $piggyBank->targetamount) {
|
||||
if (0 === bccomp($piggyBank->targetamount, '0')) {
|
||||
$preFilled['targetamount'] = '';
|
||||
}
|
||||
session()->flash('preFilled', $preFilled);
|
||||
@ -112,8 +113,8 @@ class EditController extends Controller
|
||||
/**
|
||||
* Update a piggy bank.
|
||||
*
|
||||
* @param PiggyBankUpdateRequest $request
|
||||
* @param PiggyBank $piggyBank
|
||||
* @param PiggyBankUpdateRequest $request
|
||||
* @param PiggyBank $piggyBank
|
||||
*
|
||||
* @return RedirectResponse|Redirector
|
||||
*/
|
||||
@ -122,7 +123,7 @@ class EditController extends Controller
|
||||
$data = $request->getPiggyBankData();
|
||||
$piggyBank = $this->piggyRepos->update($piggyBank, $data);
|
||||
|
||||
session()->flash('success', (string) trans('firefly.updated_piggy_bank', ['name' => $piggyBank->name]));
|
||||
session()->flash('success', (string)trans('firefly.updated_piggy_bank', ['name' => $piggyBank->name]));
|
||||
app('preferences')->mark();
|
||||
|
||||
// store new attachment(s):
|
||||
@ -132,7 +133,7 @@ class EditController extends Controller
|
||||
$this->attachments->saveAttachmentsForModel($piggyBank, $files);
|
||||
}
|
||||
if (null !== $files && auth()->user()->hasRole('demo')) {
|
||||
session()->flash('info', (string) trans('firefly.no_att_demo_user'));
|
||||
session()->flash('info', (string)trans('firefly.no_att_demo_user'));
|
||||
}
|
||||
|
||||
if (count($this->attachments->getMessages()->get('attachments')) > 0) {
|
||||
@ -140,12 +141,10 @@ class EditController extends Controller
|
||||
}
|
||||
$redirect = redirect($this->getPreviousUrl('piggy-banks.edit.url'));
|
||||
|
||||
if (1 === (int) $request->get('return_to_edit')) {
|
||||
|
||||
if (1 === (int)$request->get('return_to_edit')) {
|
||||
session()->put('piggy-banks.edit.fromUpdate', true);
|
||||
|
||||
$redirect = redirect(route('piggy-banks.edit', [$piggyBank->id]));
|
||||
|
||||
}
|
||||
|
||||
return $redirect;
|
||||
|
@ -187,7 +187,7 @@ class BudgetController extends Controller
|
||||
$result[$key]['transactions']++;
|
||||
$result[$key]['sum'] = bcadd($journal['amount'], $result[$key]['sum']);
|
||||
$result[$key]['avg'] = bcdiv($result[$key]['sum'], (string) $result[$key]['transactions']);
|
||||
$result[$key]['avg_float'] = (float) $result[$key]['avg'];
|
||||
$result[$key]['avg_float'] = (float) $result[$key]['avg']; // intentional float
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -266,7 +266,7 @@ class BudgetController extends Controller
|
||||
$total = $sums[$currencyId]['sum'] ?? '0';
|
||||
$pct = '0';
|
||||
if (0 !== bccomp($sum, '0') && 0 !== bccomp($total, '9')) {
|
||||
$pct = round((float) bcmul(bcdiv($sum, $total), '100'));
|
||||
$pct = round((float) bcmul(bcdiv($sum, $total), '100')); // intentional float
|
||||
}
|
||||
$report[$budgetId]['currencies'][$currencyId]['sum_pct'] = $pct;
|
||||
}
|
||||
@ -383,7 +383,7 @@ class BudgetController extends Controller
|
||||
$result[] = [
|
||||
'description' => $journal['description'],
|
||||
'transaction_group_id' => $journal['transaction_group_id'],
|
||||
'amount_float' => (float) $journal['amount'],
|
||||
'amount_float' => (float) $journal['amount'], // intentional float
|
||||
'amount' => $journal['amount'],
|
||||
'date' => $journal['date']->isoFormat($this->monthAndDayFormat),
|
||||
'date_sort' => $journal['date']->format('Y-m-d'),
|
||||
|
@ -301,7 +301,7 @@ class CategoryController extends Controller
|
||||
$result[$key]['transactions']++;
|
||||
$result[$key]['sum'] = bcadd($journal['amount'], $result[$key]['sum']);
|
||||
$result[$key]['avg'] = bcdiv($result[$key]['sum'], (string) $result[$key]['transactions']);
|
||||
$result[$key]['avg_float'] = (float) $result[$key]['avg'];
|
||||
$result[$key]['avg_float'] = (float) $result[$key]['avg']; // intentional float
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -137,6 +137,7 @@ class DeleteController extends Controller
|
||||
Log::debug(sprintf('Now going to trigger updated account event for account #%d', $account->id));
|
||||
event(new UpdatedAccount($account));
|
||||
}
|
||||
app('preferences')->mark();
|
||||
|
||||
|
||||
return redirect($this->getPreviousUrl('transactions.delete.url'));
|
||||
|
@ -146,7 +146,7 @@ class MassController extends Controller
|
||||
|
||||
// reverse amounts
|
||||
foreach ($journals as $index => $journal) {
|
||||
$journals[$index]['amount'] = number_format((float) app('steam')->positive($journal['amount']), $journal['currency_decimal_places'], '.', '');
|
||||
$journals[$index]['amount'] = app('steam')->bcround(app('steam')->positive($journal['amount']), $journal['currency_decimal_places']);
|
||||
$journals[$index]['foreign_amount'] = null === $journal['foreign_amount'] ?
|
||||
null : app('steam')->positive($journal['foreign_amount']);
|
||||
}
|
||||
|
@ -45,7 +45,7 @@ class PiggyBankUpdateRequest extends FormRequest
|
||||
'name' => $this->convertString('name'),
|
||||
'startdate' => $this->getCarbonDate('startdate'),
|
||||
'account_id' => $this->convertInteger('account_id'),
|
||||
'targetamount' => $this->convertString('targetamount'),
|
||||
'targetamount' => trim($this->convertString('targetamount')),
|
||||
'targetdate' => $this->getCarbonDate('targetdate'),
|
||||
'notes' => $this->stringWithNewlines('notes'),
|
||||
'object_group_title' => $this->convertString('object_group'),
|
||||
|
@ -25,6 +25,7 @@ namespace FireflyIII\Providers;
|
||||
use Exception;
|
||||
use FireflyIII\Events\ActuallyLoggedIn;
|
||||
use FireflyIII\Events\AdminRequestedTestMessage;
|
||||
use FireflyIII\Events\ChangedPiggyBankAmount;
|
||||
use FireflyIII\Events\DestroyedTransactionGroup;
|
||||
use FireflyIII\Events\DetectedNewIPAddress;
|
||||
use FireflyIII\Events\RegisteredUser;
|
||||
@ -140,6 +141,11 @@ class EventServiceProvider extends ServiceProvider
|
||||
WarnUserAboutBill::class => [
|
||||
'FireflyIII\Handlers\Events\BillEventHandler@warnAboutBill',
|
||||
],
|
||||
|
||||
// piggy bank related events:
|
||||
ChangedPiggyBankAmount::class => [
|
||||
'FireflyIII\Handlers\Events\PiggyBankEventHandler@changePiggyAmount',
|
||||
],
|
||||
];
|
||||
|
||||
/**
|
||||
|
@ -140,7 +140,7 @@ class AccountTasker implements AccountTaskerInterface
|
||||
// Obtain a list of columns
|
||||
$sum = [];
|
||||
foreach ($report['accounts'] as $accountId => $row) {
|
||||
$sum[$accountId] = (float) $row['sum'];
|
||||
$sum[$accountId] = (float) $row['sum']; // intentional float
|
||||
}
|
||||
|
||||
array_multisort($sum, SORT_ASC, $report['accounts']);
|
||||
@ -235,7 +235,7 @@ class AccountTasker implements AccountTaskerInterface
|
||||
// Obtain a list of columns
|
||||
$sum = [];
|
||||
foreach ($report['accounts'] as $accountId => $row) {
|
||||
$sum[$accountId] = (float) $row['sum'];
|
||||
$sum[$accountId] = (float) $row['sum']; // intentional float
|
||||
}
|
||||
|
||||
array_multisort($sum, SORT_DESC, $report['accounts']);
|
||||
|
@ -138,7 +138,7 @@ class NoBudgetRepository implements NoBudgetRepositoryInterface
|
||||
'currency_name' => $currency['name'],
|
||||
'currency_symbol' => $currency['symbol'],
|
||||
'currency_decimal_places' => $currency['decimal_places'],
|
||||
'amount' => number_format((float) $spent, $currency['decimal_places'], '.', ''),
|
||||
'amount' => app('steam')->bcround($spent, $currency['decimal_places']),
|
||||
];
|
||||
}
|
||||
|
||||
|
@ -275,7 +275,7 @@ class OperationsRepository implements OperationsRepositoryInterface
|
||||
'currency_name' => $currency['name'],
|
||||
'currency_symbol' => $currency['symbol'],
|
||||
'currency_decimal_places' => $currency['decimal_places'],
|
||||
'amount' => number_format((float) $spent, $currency['decimal_places'], '.', ''),
|
||||
'amount' => app('steam')->bcround($spent, $currency['decimal_places']),
|
||||
];
|
||||
}
|
||||
|
||||
|
@ -24,17 +24,16 @@ declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Repositories\PiggyBank;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use Exception;
|
||||
use FireflyIII\Events\ChangedPiggyBankAmount;
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Models\Note;
|
||||
use FireflyIII\Models\PiggyBank;
|
||||
use FireflyIII\Models\PiggyBankEvent;
|
||||
use FireflyIII\Models\PiggyBankRepetition;
|
||||
use FireflyIII\Models\TransactionJournal;
|
||||
use FireflyIII\Repositories\ObjectGroup\CreatesObjectGroups;
|
||||
use Illuminate\Database\QueryException;
|
||||
use Log;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
/**
|
||||
* Trait ModifiesPiggyBanks
|
||||
@ -44,12 +43,12 @@ trait ModifiesPiggyBanks
|
||||
use CreatesObjectGroups;
|
||||
|
||||
/**
|
||||
* @param PiggyBank $piggyBank
|
||||
* @param string $amount
|
||||
*
|
||||
* @param PiggyBank $piggyBank
|
||||
* @param string $amount
|
||||
* @param TransactionJournal|null $journal
|
||||
* @return bool
|
||||
*/
|
||||
public function addAmount(PiggyBank $piggyBank, string $amount): bool
|
||||
public function addAmount(PiggyBank $piggyBank, string $amount, ?TransactionJournal $journal = null): bool
|
||||
{
|
||||
$repetition = $this->getRepetition($piggyBank);
|
||||
if (null === $repetition) {
|
||||
@ -59,30 +58,34 @@ trait ModifiesPiggyBanks
|
||||
$repetition->currentamount = bcadd($currentAmount, $amount);
|
||||
$repetition->save();
|
||||
|
||||
// create event
|
||||
//$this->createEvent($piggyBank, $amount);
|
||||
Log::debug('addAmount: Trigger change for positive amount.');
|
||||
event(new ChangedPiggyBankAmount($piggyBank, $amount, $journal, null));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param PiggyBankRepetition $repetition
|
||||
* @param string $amount
|
||||
* @param PiggyBankRepetition $repetition
|
||||
* @param string $amount
|
||||
*
|
||||
* @return string
|
||||
* @return void
|
||||
*/
|
||||
public function addAmountToRepetition(PiggyBankRepetition $repetition, string $amount): string
|
||||
public function addAmountToRepetition(PiggyBankRepetition $repetition, string $amount, TransactionJournal $journal): void
|
||||
{
|
||||
$newAmount = bcadd($repetition->currentamount, $amount);
|
||||
$repetition->currentamount = $newAmount;
|
||||
$repetition->save();
|
||||
|
||||
return $newAmount;
|
||||
Log::debug(sprintf('addAmountToRepetition: %s', $amount));
|
||||
if (-1 === bccomp($amount, '0')) {
|
||||
Log::debug('Remove amount.');
|
||||
$this->removeAmount($repetition->piggyBank, bcmul($amount, '-1'), $journal);
|
||||
}
|
||||
if (1 === bccomp($amount, '0')) {
|
||||
Log::debug('Add amount.');
|
||||
$this->addAmount($repetition->piggyBank, $amount, $journal);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param PiggyBank $piggyBank
|
||||
* @param string $amount
|
||||
* @param PiggyBank $piggyBank
|
||||
* @param string $amount
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
@ -90,10 +93,10 @@ trait ModifiesPiggyBanks
|
||||
{
|
||||
$today = today(config('app.timezone'));
|
||||
$leftOnAccount = $this->leftOnAccount($piggyBank, $today);
|
||||
$savedSoFar = (string) $this->getRepetition($piggyBank)->currentamount;
|
||||
$savedSoFar = (string)$this->getRepetition($piggyBank)->currentamount;
|
||||
$maxAmount = $leftOnAccount;
|
||||
$leftToSave = null;
|
||||
if (0.0 !== (float) $piggyBank->targetamount) {
|
||||
if (0 !== bccomp($piggyBank->targetamount, '0')) {
|
||||
$leftToSave = bcsub($piggyBank->targetamount, $savedSoFar);
|
||||
$maxAmount = 1 === bccomp($leftOnAccount, $leftToSave) ? $leftToSave : $leftOnAccount;
|
||||
}
|
||||
@ -111,8 +114,8 @@ trait ModifiesPiggyBanks
|
||||
}
|
||||
|
||||
/**
|
||||
* @param PiggyBank $piggyBank
|
||||
* @param string $amount
|
||||
* @param PiggyBank $piggyBank
|
||||
* @param string $amount
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
@ -128,25 +131,7 @@ trait ModifiesPiggyBanks
|
||||
}
|
||||
|
||||
/**
|
||||
* @param PiggyBank $piggyBank
|
||||
* @param string $amount
|
||||
* @param TransactionJournal $journal
|
||||
*
|
||||
* @return PiggyBankEvent
|
||||
*/
|
||||
public function createEventWithJournal(PiggyBank $piggyBank, string $amount, TransactionJournal $journal): PiggyBankEvent
|
||||
{
|
||||
return PiggyBankEvent::create(
|
||||
[
|
||||
'piggy_bank_id' => $piggyBank->id,
|
||||
'transaction_journal_id' => $journal->id,
|
||||
'date' => $journal->date->format('Y-m-d'),
|
||||
'amount' => $amount]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param PiggyBank $piggyBank
|
||||
* @param PiggyBank $piggyBank
|
||||
*
|
||||
* @return bool
|
||||
* @throws Exception
|
||||
@ -160,12 +145,12 @@ trait ModifiesPiggyBanks
|
||||
}
|
||||
|
||||
/**
|
||||
* @param PiggyBank $piggyBank
|
||||
* @param string $amount
|
||||
* @param PiggyBank $piggyBank
|
||||
* @param string $amount
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function removeAmount(PiggyBank $piggyBank, string $amount): bool
|
||||
public function removeAmount(PiggyBank $piggyBank, string $amount, ?TransactionJournal $journal = null): bool
|
||||
{
|
||||
$repetition = $this->getRepetition($piggyBank);
|
||||
if (null === $repetition) {
|
||||
@ -174,27 +159,12 @@ trait ModifiesPiggyBanks
|
||||
$repetition->currentamount = bcsub($repetition->currentamount, $amount);
|
||||
$repetition->save();
|
||||
|
||||
// create event
|
||||
$this->createEvent($piggyBank, bcmul($amount, '-1'));
|
||||
Log::debug('addAmount: Trigger change for negative amount.');
|
||||
event(new ChangedPiggyBankAmount($piggyBank, bcmul($amount, '-1'), $journal, null));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param PiggyBank $piggyBank
|
||||
* @param string $amount
|
||||
*
|
||||
* @return PiggyBankEvent
|
||||
*/
|
||||
public function createEvent(PiggyBank $piggyBank, string $amount): PiggyBankEvent
|
||||
{
|
||||
if (0 === bccomp('0', $amount)) {
|
||||
return new PiggyBankEvent;
|
||||
}
|
||||
|
||||
return PiggyBankEvent::create(['date' => Carbon::now(), 'amount' => $amount, 'piggy_bank_id' => $piggyBank->id]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
@ -206,8 +176,8 @@ trait ModifiesPiggyBanks
|
||||
}
|
||||
|
||||
/**
|
||||
* @param PiggyBank $piggyBank
|
||||
* @param string $amount
|
||||
* @param PiggyBank $piggyBank
|
||||
* @param string $amount
|
||||
*
|
||||
* @return PiggyBank
|
||||
*/
|
||||
@ -225,8 +195,14 @@ trait ModifiesPiggyBanks
|
||||
$repetition->currentamount = $amount;
|
||||
$repetition->save();
|
||||
|
||||
// create event
|
||||
$this->createEvent($piggyBank, $difference);
|
||||
if (-1 === bccomp($difference, '0')) {
|
||||
Log::debug('addAmount: Trigger change for negative amount.');
|
||||
event(new ChangedPiggyBankAmount($piggyBank, bcmul($amount, '-1'), null, null));
|
||||
}
|
||||
if (1 === bccomp($difference, '0')) {
|
||||
Log::debug('addAmount: Trigger change for positive amount.');
|
||||
event(new ChangedPiggyBankAmount($piggyBank, $amount, null, null));
|
||||
}
|
||||
|
||||
return $piggyBank;
|
||||
}
|
||||
@ -242,11 +218,10 @@ trait ModifiesPiggyBanks
|
||||
}
|
||||
|
||||
return $piggyBank;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $data
|
||||
* @param array $data
|
||||
*
|
||||
* @return PiggyBank
|
||||
* @throws FireflyException
|
||||
@ -263,7 +238,7 @@ trait ModifiesPiggyBanks
|
||||
unset($piggyData['object_group_title'], $piggyData['object_group_id'], $piggyData['notes'], $piggyData['current_amount']);
|
||||
|
||||
// validate amount:
|
||||
if (array_key_exists('targetamount', $piggyData) && '' === (string) $piggyData['targetamount']) {
|
||||
if (array_key_exists('targetamount', $piggyData) && '' === (string)$piggyData['targetamount']) {
|
||||
$piggyData['targetamount'] = '0';
|
||||
}
|
||||
|
||||
@ -295,10 +270,9 @@ trait ModifiesPiggyBanks
|
||||
$piggyBank->objectGroups()->sync([$objectGroup->id]);
|
||||
$piggyBank->save();
|
||||
}
|
||||
|
||||
}
|
||||
// try also with ID
|
||||
$objectGroupId = (int) ($data['object_group_id'] ?? 0);
|
||||
$objectGroupId = (int)($data['object_group_id'] ?? 0);
|
||||
if (0 !== $objectGroupId) {
|
||||
$objectGroup = $this->findObjectGroupById($objectGroupId);
|
||||
if (null !== $objectGroup) {
|
||||
@ -318,7 +292,7 @@ trait ModifiesPiggyBanks
|
||||
$set = $this->user->piggyBanks()->orderBy('piggy_banks.order', 'ASC')->get(['piggy_banks.*']);
|
||||
$current = 1;
|
||||
foreach ($set as $piggyBank) {
|
||||
if ((int) $piggyBank->order !== $current) {
|
||||
if ((int)$piggyBank->order !== $current) {
|
||||
Log::debug(sprintf('Piggy bank #%d ("%s") was at place %d but should be on %d', $piggyBank->id, $piggyBank->name, $piggyBank->order, $current));
|
||||
$piggyBank->order = $current;
|
||||
$piggyBank->save();
|
||||
@ -332,7 +306,7 @@ trait ModifiesPiggyBanks
|
||||
*/
|
||||
public function setOrder(PiggyBank $piggyBank, int $newOrder): bool
|
||||
{
|
||||
$oldOrder = (int) $piggyBank->order;
|
||||
$oldOrder = (int)$piggyBank->order;
|
||||
Log::debug(sprintf('Will move piggy bank #%d ("%s") from %d to %d', $piggyBank->id, $piggyBank->name, $oldOrder, $newOrder));
|
||||
if ($newOrder > $oldOrder) {
|
||||
$this->user->piggyBanks()->where('piggy_banks.order', '<=', $newOrder)->where('piggy_banks.order', '>', $oldOrder)
|
||||
@ -356,8 +330,8 @@ trait ModifiesPiggyBanks
|
||||
}
|
||||
|
||||
/**
|
||||
* @param PiggyBank $piggyBank
|
||||
* @param string $note
|
||||
* @param PiggyBank $piggyBank
|
||||
* @param string $note
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
@ -387,8 +361,8 @@ trait ModifiesPiggyBanks
|
||||
}
|
||||
|
||||
/**
|
||||
* @param PiggyBank $piggyBank
|
||||
* @param array $data
|
||||
* @param PiggyBank $piggyBank
|
||||
* @param array $data
|
||||
*
|
||||
* @return PiggyBank
|
||||
*/
|
||||
@ -396,12 +370,12 @@ trait ModifiesPiggyBanks
|
||||
{
|
||||
$piggyBank = $this->updateProperties($piggyBank, $data);
|
||||
if (array_key_exists('notes', $data)) {
|
||||
$this->updateNote($piggyBank, (string) $data['notes']);
|
||||
$this->updateNote($piggyBank, (string)$data['notes']);
|
||||
}
|
||||
|
||||
// update the order of the piggy bank:
|
||||
$oldOrder = (int) $piggyBank->order;
|
||||
$newOrder = (int) ($data['order'] ?? $oldOrder);
|
||||
$oldOrder = (int)$piggyBank->order;
|
||||
$newOrder = (int)($data['order'] ?? $oldOrder);
|
||||
if ($oldOrder !== $newOrder) {
|
||||
$this->setOrder($piggyBank, $newOrder);
|
||||
}
|
||||
@ -409,9 +383,11 @@ trait ModifiesPiggyBanks
|
||||
// if the piggy bank is now smaller than the current relevant rep,
|
||||
// remove money from the rep.
|
||||
$repetition = $this->getRepetition($piggyBank);
|
||||
if (null !== $repetition && $repetition->currentamount > $piggyBank->targetamount && 0.0 !== (float) $piggyBank->targetamount) {
|
||||
$diff = bcsub($piggyBank->targetamount, $repetition->currentamount);
|
||||
$this->createEvent($piggyBank, $diff);
|
||||
if (null !== $repetition && $repetition->currentamount > $piggyBank->targetamount && 0 !== bccomp($piggyBank->targetamount, '0')) {
|
||||
$difference = bcsub($piggyBank->targetamount, $repetition->currentamount);
|
||||
|
||||
// an amount will be removed, create "negative" event:
|
||||
event(new ChangedPiggyBankAmount($piggyBank, $difference, null, null));
|
||||
|
||||
$repetition->currentamount = $piggyBank->targetamount;
|
||||
$repetition->save();
|
||||
@ -419,7 +395,7 @@ trait ModifiesPiggyBanks
|
||||
|
||||
// update using name:
|
||||
if (array_key_exists('object_group_title', $data)) {
|
||||
$objectGroupTitle = (string) $data['object_group_title'];
|
||||
$objectGroupTitle = (string)$data['object_group_title'];
|
||||
if ('' !== $objectGroupTitle) {
|
||||
$objectGroup = $this->findOrCreateObjectGroup($objectGroupTitle);
|
||||
if (null !== $objectGroup) {
|
||||
@ -438,7 +414,7 @@ trait ModifiesPiggyBanks
|
||||
|
||||
// try also with ID:
|
||||
if (array_key_exists('object_group_id', $data)) {
|
||||
$objectGroupId = (int) ($data['object_group_id'] ?? 0);
|
||||
$objectGroupId = (int)($data['object_group_id'] ?? 0);
|
||||
if (0 !== $objectGroupId) {
|
||||
$objectGroup = $this->findObjectGroupById($objectGroupId);
|
||||
if (null !== $objectGroup) {
|
||||
@ -454,8 +430,8 @@ trait ModifiesPiggyBanks
|
||||
}
|
||||
|
||||
/**
|
||||
* @param PiggyBank $piggyBank
|
||||
* @param array $data
|
||||
* @param PiggyBank $piggyBank
|
||||
* @param array $data
|
||||
*
|
||||
* @return PiggyBank
|
||||
*/
|
||||
@ -465,17 +441,19 @@ trait ModifiesPiggyBanks
|
||||
$piggyBank->name = $data['name'];
|
||||
}
|
||||
if (array_key_exists('account_id', $data) && 0 !== $data['account_id']) {
|
||||
$piggyBank->account_id = (int) $data['account_id'];
|
||||
$piggyBank->account_id = (int)$data['account_id'];
|
||||
}
|
||||
if (array_key_exists('targetamount', $data) && '' !== $data['targetamount']) {
|
||||
$piggyBank->targetamount = $data['targetamount'];
|
||||
}
|
||||
if (array_key_exists('targetamount', $data) && '' === $data['targetamount']) {
|
||||
$piggyBank->targetamount = '0';
|
||||
}
|
||||
if (array_key_exists('targetdate', $data) && '' !== $data['targetdate']) {
|
||||
$piggyBank->targetdate = $data['targetdate'];
|
||||
}
|
||||
if (array_key_exists('startdate', $data)) {
|
||||
$piggyBank->startdate = $data['startdate'];
|
||||
|
||||
}
|
||||
$piggyBank->save();
|
||||
|
||||
|
@ -37,20 +37,18 @@ use Illuminate\Support\Collection;
|
||||
interface PiggyBankRepositoryInterface
|
||||
{
|
||||
/**
|
||||
* @param PiggyBank $piggyBank
|
||||
* @param string $amount
|
||||
*
|
||||
* @param PiggyBank $piggyBank
|
||||
* @param string $amount
|
||||
* @param TransactionJournal|null $journal
|
||||
* @return bool
|
||||
*/
|
||||
public function addAmount(PiggyBank $piggyBank, string $amount): bool;
|
||||
public function addAmount(PiggyBank $piggyBank, string $amount, ?TransactionJournal $journal = null): bool;
|
||||
|
||||
/**
|
||||
* @param PiggyBankRepetition $repetition
|
||||
* @param string $amount
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function addAmountToRepetition(PiggyBankRepetition $repetition, string $amount): string;
|
||||
public function addAmountToRepetition(PiggyBankRepetition $repetition, string $amount, TransactionJournal $journal): void;
|
||||
|
||||
/**
|
||||
* @param PiggyBank $piggyBank
|
||||
@ -68,25 +66,6 @@ interface PiggyBankRepositoryInterface
|
||||
*/
|
||||
public function canRemoveAmount(PiggyBank $piggyBank, string $amount): bool;
|
||||
|
||||
/**
|
||||
* Create a new event.
|
||||
*
|
||||
* @param PiggyBank $piggyBank
|
||||
* @param string $amount
|
||||
*
|
||||
* @return PiggyBankEvent
|
||||
*/
|
||||
public function createEvent(PiggyBank $piggyBank, string $amount): PiggyBankEvent;
|
||||
|
||||
/**
|
||||
* @param PiggyBank $piggyBank
|
||||
* @param string $amount
|
||||
* @param TransactionJournal $journal
|
||||
*
|
||||
* @return PiggyBankEvent
|
||||
*/
|
||||
public function createEventWithJournal(PiggyBank $piggyBank, string $amount, TransactionJournal $journal): PiggyBankEvent;
|
||||
|
||||
/**
|
||||
* Destroy piggy bank.
|
||||
*
|
||||
@ -218,12 +197,12 @@ interface PiggyBankRepositoryInterface
|
||||
public function leftOnAccount(PiggyBank $piggyBank, Carbon $date): string;
|
||||
|
||||
/**
|
||||
* @param PiggyBank $piggyBank
|
||||
* @param string $amount
|
||||
*
|
||||
* @param PiggyBank $piggyBank
|
||||
* @param string $amount
|
||||
* @param TransactionJournal|null $journal
|
||||
* @return bool
|
||||
*/
|
||||
public function removeAmount(PiggyBank $piggyBank, string $amount): bool;
|
||||
public function removeAmount(PiggyBank $piggyBank, string $amount, ?TransactionJournal $journal = null): bool;
|
||||
|
||||
/**
|
||||
* @param PiggyBank $piggyBank
|
||||
|
@ -83,6 +83,7 @@ class JournalDestroyService
|
||||
$journal->notes()->delete();
|
||||
|
||||
// update events
|
||||
// TODO move to repository
|
||||
$journal->piggyBankEvents()->update(['transaction_journal_id' => null]);
|
||||
|
||||
$journal->delete();
|
||||
|
@ -99,7 +99,7 @@ class CreditRecalculateService
|
||||
}
|
||||
|
||||
/**
|
||||
* @param TransactionJournal $journal
|
||||
* @param TransactionJournal $journal
|
||||
*
|
||||
* @throws FireflyException
|
||||
*/
|
||||
@ -121,7 +121,7 @@ class CreditRecalculateService
|
||||
}
|
||||
|
||||
/**
|
||||
* @param TransactionJournal $journal
|
||||
* @param TransactionJournal $journal
|
||||
*
|
||||
* @return Account
|
||||
* @throws FireflyException
|
||||
@ -132,8 +132,8 @@ class CreditRecalculateService
|
||||
}
|
||||
|
||||
/**
|
||||
* @param TransactionJournal $journal
|
||||
* @param string $direction
|
||||
* @param TransactionJournal $journal
|
||||
* @param string $direction
|
||||
*
|
||||
* @return Account
|
||||
* @throws FireflyException
|
||||
@ -154,7 +154,7 @@ class CreditRecalculateService
|
||||
}
|
||||
|
||||
/**
|
||||
* @param TransactionJournal $journal
|
||||
* @param TransactionJournal $journal
|
||||
*
|
||||
* @return Account
|
||||
* @throws FireflyException
|
||||
@ -189,7 +189,7 @@ class CreditRecalculateService
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Account $account
|
||||
* @param Account $account
|
||||
*/
|
||||
private function processWorkAccount(Account $account): void
|
||||
{
|
||||
@ -205,7 +205,7 @@ class CreditRecalculateService
|
||||
$factory->crud($account, 'start_of_debt', $startOfDebt);
|
||||
|
||||
// get direction of liability:
|
||||
$direction = (string) $this->repository->getMetaValue($account, 'liability_direction');
|
||||
$direction = (string)$this->repository->getMetaValue($account, 'liability_direction');
|
||||
|
||||
// now loop all transactions (except opening balance and credit thing)
|
||||
$transactions = $account->transactions()->get();
|
||||
@ -220,24 +220,36 @@ class CreditRecalculateService
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Account $account
|
||||
* @param string $direction
|
||||
* @param Transaction $transaction
|
||||
* @param string $amount
|
||||
* @param Account $account
|
||||
* @param string $direction
|
||||
* @param Transaction $transaction
|
||||
* @param string $amount
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function processTransaction(Account $account, string $direction, Transaction $transaction, string $amount): string
|
||||
{
|
||||
Log::debug(sprintf('Now in %s(#%d, %s)', __METHOD__, $transaction->id, $amount));
|
||||
$journal = $transaction->transactionJournal;
|
||||
$groupId = $journal->transaction_group_id;
|
||||
$type = $journal->transactionType->type;
|
||||
$journal = $transaction->transactionJournal;
|
||||
$foreignCurrency = $transaction->foreignCurrency;
|
||||
$accountCurrency = $this->repository->getAccountCurrency($account);
|
||||
$groupId = $journal->transaction_group_id;
|
||||
$type = $journal->transactionType->type;
|
||||
|
||||
Log::debug(sprintf('Account currency is #%d (%s)', $accountCurrency->id, $accountCurrency->code));
|
||||
|
||||
if ('' === $direction) {
|
||||
Log::debug('Since direction is "", do nothing.');
|
||||
|
||||
return $amount;
|
||||
}
|
||||
// amount to use depends on the currency:
|
||||
$usedAmount = $transaction->amount;
|
||||
if (null !== $foreignCurrency && $foreignCurrency->id === $accountCurrency->id) {
|
||||
$usedAmount = $transaction->foreign_amount;
|
||||
Log::debug('Will now use foreign amount!');
|
||||
}
|
||||
|
||||
|
||||
Log::debug(sprintf('Processing group #%d, journal #%d of type "%s"', $journal->id, $groupId, $type));
|
||||
|
||||
@ -246,8 +258,8 @@ class CreditRecalculateService
|
||||
// to a credit-liability doesn't increase the amount (yet)
|
||||
if (
|
||||
$type === TransactionType::WITHDRAWAL
|
||||
&& (int) $account->id === (int) $transaction->account_id
|
||||
&& 1 === bccomp($transaction->amount, '0')
|
||||
&& (int)$account->id === (int)$transaction->account_id
|
||||
&& 1 === bccomp($usedAmount, '0')
|
||||
&& 'credit' === $direction
|
||||
) {
|
||||
Log::debug(sprintf('Is withdrawal into credit liability #%d, does not influence the amount due.', $transaction->account_id));
|
||||
@ -258,8 +270,8 @@ class CreditRecalculateService
|
||||
// likewise deposit into a credit debt does not change the amount
|
||||
if (
|
||||
$type === TransactionType::DEPOSIT
|
||||
&& (int) $account->id === (int) $transaction->account_id
|
||||
&& -1 === bccomp($transaction->amount, '0')
|
||||
&& (int)$account->id === (int)$transaction->account_id
|
||||
&& -1 === bccomp($usedAmount, '0')
|
||||
&& 'credit' === $direction
|
||||
) {
|
||||
Log::debug(sprintf('Is deposit from liability #%d,does not influence the amount left.', $transaction->account_id));
|
||||
@ -268,7 +280,7 @@ class CreditRecalculateService
|
||||
}
|
||||
|
||||
if (in_array($type, [TransactionType::WITHDRAWAL, TransactionType::DEPOSIT, TransactionType::TRANSFER], true)) {
|
||||
$amount = bcadd($amount, bcmul($transaction->amount, '-1'));
|
||||
$amount = bcadd($amount, bcmul($usedAmount, '-1'));
|
||||
}
|
||||
Log::debug(sprintf('Amount is now %s', $amount));
|
||||
|
||||
@ -276,7 +288,7 @@ class CreditRecalculateService
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Account|null $account
|
||||
* @param Account|null $account
|
||||
*/
|
||||
public function setAccount(?Account $account): void
|
||||
{
|
||||
@ -284,7 +296,7 @@ class CreditRecalculateService
|
||||
}
|
||||
|
||||
/**
|
||||
* @param TransactionGroup $group
|
||||
* @param TransactionGroup $group
|
||||
*/
|
||||
public function setGroup(TransactionGroup $group): void
|
||||
{
|
||||
|
@ -105,7 +105,7 @@ class GroupCloneService
|
||||
// add note saying "cloned".
|
||||
|
||||
// add relation.
|
||||
// clone linked piggy banks
|
||||
// TODO clone ALL linked piggy banks
|
||||
/** @var PiggyBankEvent $event */
|
||||
$event = $journal->piggyBankEvents()->first();
|
||||
if(null !== $event) {
|
||||
|
@ -1,4 +1,5 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Amount.php
|
||||
* Copyright (c) 2019 james@firefly-iii.org
|
||||
@ -42,26 +43,26 @@ class Amount
|
||||
* This method will properly format the given number, in color or "black and white",
|
||||
* as a currency, given two things: the currency required and the current locale.
|
||||
*
|
||||
* @param TransactionCurrency $format
|
||||
* @param string $amount
|
||||
* @param bool $coloured
|
||||
* @param TransactionCurrency $format
|
||||
* @param string $amount
|
||||
* @param bool $coloured
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
*/
|
||||
public function formatAnything(TransactionCurrency $format, string $amount, bool $coloured = null): string
|
||||
{
|
||||
return $this->formatFlat($format->symbol, (int) $format->decimal_places, $amount, $coloured);
|
||||
return $this->formatFlat($format->symbol, (int)$format->decimal_places, $amount, $coloured);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method will properly format the given number, in color or "black and white",
|
||||
* as a currency, given two things: the currency required and the current locale.
|
||||
*
|
||||
* @param string $symbol
|
||||
* @param int $decimalPlaces
|
||||
* @param string $amount
|
||||
* @param bool $coloured
|
||||
* @param string $symbol
|
||||
* @param int $decimalPlaces
|
||||
* @param string $amount
|
||||
* @param bool $coloured
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
@ -78,13 +79,13 @@ class Amount
|
||||
$fmt->setSymbol(NumberFormatter::CURRENCY_SYMBOL, $symbol);
|
||||
$fmt->setAttribute(NumberFormatter::MIN_FRACTION_DIGITS, $decimalPlaces);
|
||||
$fmt->setAttribute(NumberFormatter::MAX_FRACTION_DIGITS, $decimalPlaces);
|
||||
$result = $fmt->format((float) $amount);
|
||||
$result = $fmt->format((float)app('steam')->bcround($amount, $decimalPlaces)); // intentional float
|
||||
|
||||
if (true === $coloured) {
|
||||
if ($amount > 0) {
|
||||
if (1 === bccomp($amount, '0')) {
|
||||
return sprintf('<span class="text-success">%s</span>', $result);
|
||||
}
|
||||
if ($amount < 0) {
|
||||
if (-1 === bccomp($amount, '0')) {
|
||||
return sprintf('<span class="text-danger">%s</span>', $result);
|
||||
}
|
||||
|
||||
@ -133,7 +134,7 @@ class Amount
|
||||
}
|
||||
$cache->store(config('firefly.default_currency', 'EUR'));
|
||||
|
||||
return (string) config('firefly.default_currency', 'EUR');
|
||||
return (string)config('firefly.default_currency', 'EUR');
|
||||
}
|
||||
|
||||
/**
|
||||
@ -150,7 +151,7 @@ class Amount
|
||||
}
|
||||
|
||||
/**
|
||||
* @param User $user
|
||||
* @param User $user
|
||||
*
|
||||
* @return TransactionCurrency
|
||||
* @throws FireflyException
|
||||
@ -167,7 +168,7 @@ class Amount
|
||||
$currencyPrefStr = $currencyPreference ? $currencyPreference->data : 'EUR';
|
||||
|
||||
// at this point the currency preference could be encrypted, if coming from an old version.
|
||||
$currencyCode = $this->tryDecrypt((string) $currencyPrefStr);
|
||||
$currencyCode = $this->tryDecrypt((string)$currencyPrefStr);
|
||||
|
||||
// could still be json encoded:
|
||||
/** @var TransactionCurrency|null $currency */
|
||||
@ -182,7 +183,7 @@ class Amount
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $value
|
||||
* @param string $value
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
@ -251,8 +252,8 @@ class Amount
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $info
|
||||
* @param string $field
|
||||
* @param array $info
|
||||
* @param string $field
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
@ -268,10 +269,10 @@ class Amount
|
||||
* string $sign = $localeconv['negative_sign']
|
||||
* bool $csPrecedes = $localeconv['n_cs_precedes'].
|
||||
*
|
||||
* @param bool $sepBySpace
|
||||
* @param int $signPosn
|
||||
* @param string $sign
|
||||
* @param bool $csPrecedes
|
||||
* @param bool $sepBySpace
|
||||
* @param int $signPosn
|
||||
* @param string $sign
|
||||
* @param bool $csPrecedes
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
@ -326,11 +327,11 @@ class Amount
|
||||
}
|
||||
|
||||
// default is amount before currency
|
||||
$format = $posA . $posD . '%v' . $space . $posB . '%s' . $posC . $posE;
|
||||
$format = $posA.$posD.'%v'.$space.$posB.'%s'.$posC.$posE;
|
||||
|
||||
if ($csPrecedes) {
|
||||
// alternative is currency before amount
|
||||
$format = $posA . $posB . '%s' . $posC . $space . $posD . '%v' . $posE;
|
||||
$format = $posA.$posB.'%s'.$posC.$space.$posD.'%v'.$posE;
|
||||
}
|
||||
|
||||
return $format;
|
||||
|
@ -69,6 +69,7 @@ class RemoteUserGuard implements Guard
|
||||
// Get the user identifier from $_SERVER or apache filtered headers
|
||||
$header = config('auth.guard_header', 'REMOTE_USER');
|
||||
$userID = request()->server($header) ?? apache_request_headers()[$header] ?? null;
|
||||
|
||||
if (null === $userID) {
|
||||
Log::error(sprintf('No user in header "%s".', $header));
|
||||
throw new FireflyException('The guard header was unexpectedly empty. See the logs.');
|
||||
@ -81,10 +82,14 @@ class RemoteUserGuard implements Guard
|
||||
$header = config('auth.guard_email');
|
||||
|
||||
if (null !== $header) {
|
||||
$emailAddress = (string) (request()->server($header) ?? null);
|
||||
$emailAddress = (string) (request()->server($header) ?? apache_request_headers()[$header] ?? null);
|
||||
$preference = app('preferences')->getForUser($retrievedUser, 'remote_guard_alt_email');
|
||||
|
||||
if (null !== $emailAddress && null === $preference && $emailAddress !== $userID) {
|
||||
if ('' !== $emailAddress && null === $preference && $emailAddress !== $userID) {
|
||||
app('preferences')->setForUser($retrievedUser, 'remote_guard_alt_email', $emailAddress);
|
||||
}
|
||||
// if the pref isn't null and the object returned isn't null, update the email address.
|
||||
if ('' !== $emailAddress && null !== $preference && $emailAddress !== $preference->data) {
|
||||
app('preferences')->setForUser($retrievedUser, 'remote_guard_alt_email', $emailAddress);
|
||||
}
|
||||
}
|
||||
|
@ -105,8 +105,8 @@ class WholePeriodChartGenerator
|
||||
$earnedInfoKey = sprintf('earned-in-%s', $code);
|
||||
$spentAmount = $spent[$key][$currencyId]['sum'] ?? '0';
|
||||
$earnedAmount = $earned[$key][$currencyId]['sum'] ?? '0';
|
||||
$chartData[$spentInfoKey]['entries'][$label] = round((float) $spentAmount, $currency['currency_decimal_places']);
|
||||
$chartData[$earnedInfoKey]['entries'][$label] = round((float) $earnedAmount, $currency['currency_decimal_places']);
|
||||
$chartData[$spentInfoKey]['entries'][$label] = app('steam')->bcround($spentAmount, $currency['currency_decimal_places']);
|
||||
$chartData[$earnedInfoKey]['entries'][$label] = app('steam')->bcround($earnedAmount, $currency['currency_decimal_places']);
|
||||
}
|
||||
$current = app('navigation')->addPeriod($current, $step, 0);
|
||||
}
|
||||
|
@ -92,7 +92,7 @@ class CurrencyForm
|
||||
|
||||
// make sure value is formatted nicely:
|
||||
if (null !== $value && '' !== $value) {
|
||||
$value = round((float) $value, $defaultCurrency->decimal_places);
|
||||
$value = app('steam')->bcround($value, $defaultCurrency->decimal_places);
|
||||
}
|
||||
try {
|
||||
$html = view('form.' . $view, compact('defaultCurrency', 'currencies', 'classes', 'name', 'label', 'value', 'options'))->render();
|
||||
@ -161,7 +161,7 @@ class CurrencyForm
|
||||
|
||||
// make sure value is formatted nicely:
|
||||
if (null !== $value && '' !== $value) {
|
||||
$value = round((float) $value, $defaultCurrency->decimal_places);
|
||||
$value = app('steam')->bcround($value, $defaultCurrency->decimal_places);
|
||||
}
|
||||
try {
|
||||
$html = view('form.' . $view, compact('defaultCurrency', 'currencies', 'classes', 'name', 'label', 'value', 'options'))->render();
|
||||
|
@ -863,6 +863,9 @@ class OperatorQuerySearch implements SearchInterface
|
||||
case 'attachment_notes_ends':
|
||||
$this->collector->attachmentNotesEnds($value);
|
||||
break;
|
||||
case 'sepa_ct_is':
|
||||
$this->collector->setSepaCT($value);
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,5 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Steam.php
|
||||
* Copyright (c) 2019 james@firefly-iii.org
|
||||
@ -45,26 +46,18 @@ class Steam
|
||||
{
|
||||
|
||||
/**
|
||||
* @param Account $account
|
||||
* @param Carbon $date
|
||||
* @param Account $account
|
||||
* @param Carbon $date
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function balanceIgnoreVirtual(Account $account, Carbon $date): string
|
||||
{
|
||||
// abuse chart properties:
|
||||
$cache = new CacheProperties;
|
||||
$cache->addProperty($account->id);
|
||||
$cache->addProperty('balance-no-virtual');
|
||||
$cache->addProperty($date);
|
||||
if ($cache->has()) {
|
||||
return $cache->get();
|
||||
}
|
||||
/** @var AccountRepositoryInterface $repository */
|
||||
$repository = app(AccountRepositoryInterface::class);
|
||||
$repository->setUser($account->user);
|
||||
|
||||
$currencyId = (int) $repository->getMetaValue($account, 'currency_id');
|
||||
$currencyId = (int)$repository->getMetaValue($account, 'currency_id');
|
||||
$transactions = $account->transactions()
|
||||
->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id')
|
||||
->where('transaction_journals.date', '<=', $date->format('Y-m-d 23:59:59'))
|
||||
@ -81,16 +74,12 @@ class Steam
|
||||
->get(['transactions.foreign_amount'])->toArray();
|
||||
|
||||
$foreignBalance = $this->sumTransactions($transactions, 'foreign_amount');
|
||||
$balance = bcadd($nativeBalance, $foreignBalance);
|
||||
|
||||
$cache->store($balance);
|
||||
|
||||
return $balance;
|
||||
return bcadd($nativeBalance, $foreignBalance);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $transactions
|
||||
* @param string $key
|
||||
* @param array $transactions
|
||||
* @param string $key
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
@ -99,7 +88,7 @@ class Steam
|
||||
$sum = '0';
|
||||
/** @var array $transaction */
|
||||
foreach ($transactions as $transaction) {
|
||||
$value = (string) ($transaction[$key] ?? '0');
|
||||
$value = (string)($transaction[$key] ?? '0');
|
||||
$value = '' === $value ? '0' : $value;
|
||||
$sum = bcadd($sum, $value);
|
||||
}
|
||||
@ -107,15 +96,38 @@ class Steam
|
||||
return $sum;
|
||||
}
|
||||
|
||||
/**
|
||||
* https://stackoverflow.com/questions/1642614/how-to-ceil-floor-and-round-bcmath-numbers
|
||||
*
|
||||
* @param null|string $number
|
||||
* @param int $precision
|
||||
* @return string
|
||||
*/
|
||||
public function bcround(?string $number, int $precision = 0): string
|
||||
{
|
||||
if(null === $number) {
|
||||
return '0';
|
||||
}
|
||||
if (str_contains($number, '.')) {
|
||||
if ($number[0] !== '-') {
|
||||
return bcadd($number, '0.'.str_repeat('0', $precision).'5', $precision);
|
||||
}
|
||||
|
||||
return bcsub($number, '0.'.str_repeat('0', $precision).'5', $precision);
|
||||
}
|
||||
|
||||
return $number;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the balance for the given account during the whole range, using this format:.
|
||||
*
|
||||
* [yyyy-mm-dd] => 123,2
|
||||
*
|
||||
* @param Account $account
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
* @param TransactionCurrency|null $currency
|
||||
* @param Account $account
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
* @param TransactionCurrency|null $currency
|
||||
*
|
||||
* @return array
|
||||
* @throws FireflyException
|
||||
@ -146,7 +158,7 @@ class Steam
|
||||
$repository->setUser($account->user);
|
||||
$currency = $repository->getAccountCurrency($account) ?? app('amount')->getDefaultCurrencyByUser($account->user);
|
||||
}
|
||||
$currencyId = (int) $currency->id;
|
||||
$currencyId = (int)$currency->id;
|
||||
|
||||
$start->addDay();
|
||||
|
||||
@ -174,14 +186,14 @@ class Steam
|
||||
/** @var Transaction $entry */
|
||||
foreach ($set as $entry) {
|
||||
// normal amount and foreign amount
|
||||
$modified = null === $entry->modified ? '0' : (string) $entry->modified;
|
||||
$foreignModified = null === $entry->modified_foreign ? '0' : (string) $entry->modified_foreign;
|
||||
$modified = null === $entry->modified ? '0' : (string)$entry->modified;
|
||||
$foreignModified = null === $entry->modified_foreign ? '0' : (string)$entry->modified_foreign;
|
||||
$amount = '0';
|
||||
if ($currencyId === (int) $entry->transaction_currency_id || 0 === $currencyId) {
|
||||
if ($currencyId === (int)$entry->transaction_currency_id || 0 === $currencyId) {
|
||||
// use normal amount:
|
||||
$amount = $modified;
|
||||
}
|
||||
if ($currencyId === (int) $entry->foreign_currency_id) {
|
||||
if ($currencyId === (int)$entry->foreign_currency_id) {
|
||||
// use foreign amount:
|
||||
$amount = $foreignModified;
|
||||
}
|
||||
@ -200,9 +212,9 @@ class Steam
|
||||
/**
|
||||
* Gets balance at the end of current month by default
|
||||
*
|
||||
* @param Account $account
|
||||
* @param Carbon $date
|
||||
* @param TransactionCurrency|null $currency
|
||||
* @param Account $account
|
||||
* @param Carbon $date
|
||||
* @param TransactionCurrency|null $currency
|
||||
*
|
||||
* @return string
|
||||
* @throws FireflyException
|
||||
@ -240,7 +252,7 @@ class Steam
|
||||
->get(['transactions.foreign_amount'])->toArray();
|
||||
$foreignBalance = $this->sumTransactions($transactions, 'foreign_amount');
|
||||
$balance = bcadd($nativeBalance, $foreignBalance);
|
||||
$virtual = null === $account->virtual_balance ? '0' : (string) $account->virtual_balance;
|
||||
$virtual = null === $account->virtual_balance ? '0' : (string)$account->virtual_balance;
|
||||
$balance = bcadd($balance, $virtual);
|
||||
|
||||
$cache->store($balance);
|
||||
@ -251,8 +263,8 @@ class Steam
|
||||
/**
|
||||
* This method always ignores the virtual balance.
|
||||
*
|
||||
* @param Collection $accounts
|
||||
* @param Carbon $date
|
||||
* @param Collection $accounts
|
||||
* @param Carbon $date
|
||||
*
|
||||
* @return array
|
||||
* @throws JsonException
|
||||
@ -284,8 +296,8 @@ class Steam
|
||||
/**
|
||||
* Same as above, but also groups per currency.
|
||||
*
|
||||
* @param Collection $accounts
|
||||
* @param Carbon $date
|
||||
* @param Collection $accounts
|
||||
* @param Carbon $date
|
||||
*
|
||||
* @return array
|
||||
* @throws JsonException
|
||||
@ -315,8 +327,8 @@ class Steam
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Account $account
|
||||
* @param Carbon $date
|
||||
* @param Account $account
|
||||
* @param Carbon $date
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
@ -338,7 +350,7 @@ class Steam
|
||||
$return = [];
|
||||
/** @var stdClass $entry */
|
||||
foreach ($balances as $entry) {
|
||||
$return[(int) $entry->transaction_currency_id] = (string) $entry->sum_for_currency;
|
||||
$return[(int)$entry->transaction_currency_id] = (string)$entry->sum_for_currency;
|
||||
}
|
||||
$cache->store($return);
|
||||
|
||||
@ -346,7 +358,7 @@ class Steam
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $string
|
||||
* @param string $string
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
@ -405,7 +417,7 @@ class Steam
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $accounts
|
||||
* @param array $accounts
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
@ -421,7 +433,7 @@ class Steam
|
||||
foreach ($set as $entry) {
|
||||
$date = new Carbon($entry->max_date, config('app.timezone'));
|
||||
$date->setTimezone(config('app.timezone'));
|
||||
$list[(int) $entry->account_id] = $date;
|
||||
$list[(int)$entry->account_id] = $date;
|
||||
}
|
||||
|
||||
return $list;
|
||||
@ -468,7 +480,7 @@ class Steam
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $locale
|
||||
* @param string $locale
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
@ -501,8 +513,8 @@ class Steam
|
||||
/**
|
||||
* Make sure URL is safe.
|
||||
*
|
||||
* @param string $unknownUrl
|
||||
* @param string $safeUrl
|
||||
* @param string $unknownUrl
|
||||
* @param string $safeUrl
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
@ -527,7 +539,7 @@ class Steam
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $amount
|
||||
* @param string $amount
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
@ -551,7 +563,7 @@ class Steam
|
||||
* Convert a scientific notation to float
|
||||
* Additionally fixed a problem with PHP <= 5.2.x with big integers
|
||||
*
|
||||
* @param string $value
|
||||
* @param string $value
|
||||
* @return string
|
||||
*/
|
||||
public function floatalize(string $value): string
|
||||
@ -566,15 +578,15 @@ class Steam
|
||||
$post = strlen(substr($number, strpos($number, '.') + 1));
|
||||
$mantis = substr($value, strpos($value, 'E') + 1);
|
||||
if ($mantis < 0) {
|
||||
$post += abs((int) $mantis);
|
||||
$post += abs((int)$mantis);
|
||||
}
|
||||
return number_format((float) $value, $post, '.', '');
|
||||
return number_format((float)$value, $post, '.', '');
|
||||
}
|
||||
return number_format((float) $value, 0, '.', '');
|
||||
return number_format((float)$value, 0, '.', '');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string|null $amount
|
||||
* @param string|null $amount
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
@ -588,7 +600,7 @@ class Steam
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $string
|
||||
* @param string $string
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
@ -600,28 +612,28 @@ class Steam
|
||||
// has a K in it, remove the K and multiply by 1024.
|
||||
$bytes = bcmul(rtrim($string, 'k'), '1024');
|
||||
|
||||
return (int) $bytes;
|
||||
return (int)$bytes;
|
||||
}
|
||||
|
||||
if (false !== stripos($string, 'm')) {
|
||||
// has a M in it, remove the M and multiply by 1048576.
|
||||
$bytes = bcmul(rtrim($string, 'm'), '1048576');
|
||||
|
||||
return (int) $bytes;
|
||||
return (int)$bytes;
|
||||
}
|
||||
|
||||
if (false !== stripos($string, 'g')) {
|
||||
// has a G in it, remove the G and multiply by (1024)^3.
|
||||
$bytes = bcmul(rtrim($string, 'g'), '1073741824');
|
||||
|
||||
return (int) $bytes;
|
||||
return (int)$bytes;
|
||||
}
|
||||
|
||||
return (int) $string;
|
||||
return (int)$string;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $amount
|
||||
* @param string $amount
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
|
@ -221,7 +221,7 @@ class TransactionGroupTwig extends AbstractExtension
|
||||
/** @var Transaction $first */
|
||||
$first = $journal->transactions()->where('amount', '<', 0)->first();
|
||||
|
||||
return null !== $first->foreign_amount;
|
||||
return '' !== $first->foreign_amount;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -237,7 +237,7 @@ class TransactionGroupTwig extends AbstractExtension
|
||||
/** @var Transaction $first */
|
||||
$first = $journal->transactions()->where('amount', '<', 0)->first();
|
||||
$currency = $first->foreignCurrency;
|
||||
$amount = $first->foreign_amount ?? '0';
|
||||
$amount = '' === $first->foreign_amount ? '0' : $first->foreign_amount;
|
||||
$colored = true;
|
||||
$sourceType = $first->account()->first()->accountType()->first()->type;
|
||||
|
||||
|
@ -27,6 +27,7 @@ namespace FireflyIII\TransactionRules\Actions;
|
||||
use FireflyIII\Models\PiggyBank;
|
||||
use FireflyIII\Models\RuleAction;
|
||||
use FireflyIII\Models\Transaction;
|
||||
use FireflyIII\Models\TransactionJournal;
|
||||
use FireflyIII\Models\TransactionType;
|
||||
use FireflyIII\Repositories\PiggyBank\PiggyBankRepositoryInterface;
|
||||
use FireflyIII\User;
|
||||
@ -37,14 +38,12 @@ use Log;
|
||||
*/
|
||||
class UpdatePiggybank implements ActionInterface
|
||||
{
|
||||
|
||||
/** @var RuleAction The rule action */
|
||||
private $action;
|
||||
private RuleAction $action;
|
||||
|
||||
/**
|
||||
* TriggerInterface constructor.
|
||||
*
|
||||
* @param RuleAction $action
|
||||
* @param RuleAction $action
|
||||
*/
|
||||
public function __construct(RuleAction $action)
|
||||
{
|
||||
@ -59,9 +58,10 @@ class UpdatePiggybank implements ActionInterface
|
||||
Log::debug(sprintf('Triggered rule action UpdatePiggybank on journal #%d', $journal['transaction_journal_id']));
|
||||
|
||||
// refresh the transaction type.
|
||||
$user = User::find($journal['user_id']);
|
||||
$user = User::find($journal['user_id']);
|
||||
/** @var TransactionJournal $journalObj */
|
||||
$journalObj = $user->transactionJournals()->find($journal['transaction_journal_id']);
|
||||
$type = TransactionType::find((int) $journalObj->transaction_type_id);
|
||||
$type = TransactionType::find((int)$journalObj->transaction_type_id);
|
||||
$journal['transaction_type_type'] = $type->type;
|
||||
|
||||
if (TransactionType::TRANSFER !== $journal['transaction_type_type']) {
|
||||
@ -70,10 +70,10 @@ class UpdatePiggybank implements ActionInterface
|
||||
return false;
|
||||
}
|
||||
|
||||
$piggyBank = $this->findPiggybank($user);
|
||||
$piggyBank = $this->findPiggyBank($user);
|
||||
if (null === $piggyBank) {
|
||||
Log::info(
|
||||
sprintf('No piggy bank names "%s", cant execute action #%d of rule #%d', $this->action->action_value, $this->action->id, $this->action->rule_id)
|
||||
sprintf('No piggy bank named "%s", cant execute action #%d of rule #%d', $this->action->action_value, $this->action->id, $this->action->rule_id)
|
||||
);
|
||||
|
||||
return false;
|
||||
@ -82,25 +82,27 @@ class UpdatePiggybank implements ActionInterface
|
||||
Log::debug(sprintf('Found piggy bank #%d ("%s")', $piggyBank->id, $piggyBank->name));
|
||||
|
||||
/** @var Transaction $source */
|
||||
$source = Transaction::where('transaction_journal_id', $journal['transaction_journal_id'])->where('amount', '<', 0)->first();
|
||||
/** @var Transaction $destination */
|
||||
$destination = Transaction::where('transaction_journal_id', $journal['transaction_journal_id'])->where('amount', '>', 0)->first();
|
||||
$source = $journalObj->transactions()->where('amount', '<', 0)->first();
|
||||
$destination = $journalObj->transactions()->where('amount', '>', 0)->first();
|
||||
|
||||
if ((int) $source->account_id === (int) $piggyBank->account_id) {
|
||||
Log::debug('Piggy bank account is linked to source, so remove amount.');
|
||||
if ((int)$source->account_id === (int)$piggyBank->account_id) {
|
||||
Log::debug('Piggy bank account is linked to source, so remove amount from piggy bank.');
|
||||
$this->removeAmount($journal, $piggyBank, $destination->amount);
|
||||
|
||||
return true;
|
||||
}
|
||||
if ((int) $destination->account_id === (int) $piggyBank->account_id) {
|
||||
Log::debug('Piggy bank account is linked to source, so add amount.');
|
||||
if ((int)$destination->account_id === (int)$piggyBank->account_id) {
|
||||
Log::debug('Piggy bank account is linked to source, so add amount to piggy bank.');
|
||||
$this->addAmount($journal, $piggyBank, $destination->amount);
|
||||
|
||||
return true;
|
||||
}
|
||||
Log::info(
|
||||
sprintf(
|
||||
'Piggy bank is not linked to source ("#%d") or destination ("#%d"), so no action will be taken.', $source->account_id, $destination->account_id
|
||||
'Piggy bank is not linked to source ("#%d") or destination ("#%d"), so no action will be taken.',
|
||||
$source->account_id,
|
||||
$destination->account_id
|
||||
)
|
||||
);
|
||||
|
||||
@ -108,30 +110,30 @@ class UpdatePiggybank implements ActionInterface
|
||||
}
|
||||
|
||||
/**
|
||||
* @param User $user
|
||||
* @param User $user
|
||||
*
|
||||
* @return PiggyBank|null
|
||||
*/
|
||||
private function findPiggybank(User $user): ?PiggyBank
|
||||
private function findPiggyBank(User $user): ?PiggyBank
|
||||
{
|
||||
return $user->piggyBanks()->where('piggy_banks.name', $this->action->action_value)->first();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $journalArray
|
||||
* @param PiggyBank $piggyBank
|
||||
* @param string $amount
|
||||
* @param PiggyBank $piggyBank
|
||||
* @param TransactionJournal $journal
|
||||
* @param string $amount
|
||||
* @return void
|
||||
*/
|
||||
private function removeAmount(array $journalArray, PiggyBank $piggyBank, string $amount): void
|
||||
private function removeAmount(PiggyBank $piggyBank, TransactionJournal $journal, string $amount): void
|
||||
{
|
||||
$user = User::find($journalArray['user_id']);
|
||||
$journal = $user->transactionJournals()->find($journalArray['transaction_journal_id']);
|
||||
$repository = app(PiggyBankRepositoryInterface::class);
|
||||
$repository->setUser($journal->user);
|
||||
|
||||
// how much can we remove from piggy bank?
|
||||
// how much can we remove from this piggy bank?
|
||||
$toRemove = $repository->getCurrentAmount($piggyBank);
|
||||
Log::debug(sprintf('Amount is %s, max to remove is %s', $amount, $toRemove));
|
||||
|
||||
// if $amount is bigger than $toRemove, shrink it.
|
||||
$amount = -1 === bccomp($amount, $toRemove) ? $amount : $toRemove;
|
||||
Log::debug(sprintf('Amount is now %s', $amount));
|
||||
@ -151,19 +153,17 @@ class UpdatePiggybank implements ActionInterface
|
||||
}
|
||||
Log::debug(sprintf('Will now remove %s from piggy bank.', $amount));
|
||||
|
||||
$repository->removeAmount($piggyBank, $amount);
|
||||
$repository->createEventWithJournal($piggyBank, app('steam')->negative($amount), $journal);
|
||||
$repository->removeAmount($piggyBank, $amount, $journal);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $journalArray
|
||||
* @param PiggyBank $piggyBank
|
||||
* @param string $amount
|
||||
* @param PiggyBank $piggyBank
|
||||
* @param TransactionJournal $journal
|
||||
* @param string $amount
|
||||
* @return void
|
||||
*/
|
||||
private function addAmount(array $journalArray, PiggyBank $piggyBank, string $amount): void
|
||||
private function addAmount(PiggyBank $piggyBank, TransactionJournal $journal, string $amount): void
|
||||
{
|
||||
$user = User::find($journalArray['user_id']);
|
||||
$journal = $user->transactionJournals()->find($journalArray['transaction_journal_id']);
|
||||
$repository = app(PiggyBankRepositoryInterface::class);
|
||||
$repository->setUser($journal->user);
|
||||
|
||||
@ -190,7 +190,6 @@ class UpdatePiggybank implements ActionInterface
|
||||
}
|
||||
Log::debug(sprintf('Will now add %s to piggy bank.', $amount));
|
||||
|
||||
$repository->addAmount($piggyBank, $amount);
|
||||
$repository->createEventWithJournal($piggyBank, app('steam')->positive($amount), $journal);
|
||||
$repository->addAmount($piggyBank, $amount, $journal);
|
||||
}
|
||||
}
|
||||
|
@ -444,11 +444,11 @@ trait TransactionValidation
|
||||
}
|
||||
$type = $this->getTransactionType($transactionGroup, $transactions);
|
||||
|
||||
// compare source ID's, destination ID's, source names and destination names.
|
||||
// compare source IDs, destination IDs, source names and destination names.
|
||||
// I think I can get away with one combination being equal, as long as the rest
|
||||
// of the code picks up on this as well.
|
||||
// either way all fields must be blank or all equal
|
||||
// but if ID's are equal don't bother with the names.
|
||||
// but if IDs are equal don't bother with the names.
|
||||
$comparison = $this->collectComparisonData($transactions);
|
||||
$result = $this->compareAccountData($type, $comparison);
|
||||
if (false === $result) {
|
||||
|
56
changelog.md
56
changelog.md
@ -2,7 +2,35 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
This project adheres to [Semantic Versioning](http://semver.org/).
|
||||
|
||||
## 5.7.15 - 2022-05-25
|
||||
## 5.7.16 - 2022-12-25
|
||||
|
||||
### Added
|
||||
- You can now search for SEPA CT, thanks @dasJ!
|
||||
|
||||
### Changed
|
||||
- Links go to [Mastodon](https://fosstodon.org/@ff3), not Twitter.
|
||||
- Most if not all remaining float values removed. None were used in financial math.
|
||||
- Expand Laravel Passport settings.
|
||||
|
||||
### Fixed
|
||||
- [Issue 6597](https://github.com/firefly-iii/firefly-iii/issues/6597) Edit existing split transaction's source did not work properly.
|
||||
- [Issue 6610](https://github.com/firefly-iii/firefly-iii/issues/6610) Fix search for attachments
|
||||
- [Issue 6625](https://github.com/firefly-iii/firefly-iii/issues/6625) Page of the links is not displayed due to an error
|
||||
- [Issue 6701](https://github.com/firefly-iii/firefly-iii/issues/6701) Ensure remote_guard_alt_email if changed, thanks @nebulade!
|
||||
- Remove some null pointers in the code.
|
||||
- Add missing locale data
|
||||
- Fixed typo, thx @charlesteets!
|
||||
- Various issues with piggy banks
|
||||
- Clear cache after a transaction is deleted.
|
||||
- Be more clear about registrations being disabled.
|
||||
|
||||
### Security
|
||||
- Updated all packages and dependencies.
|
||||
|
||||
### API
|
||||
- Fix API endpoint that would not accept two of the same dates.
|
||||
|
||||
## 5.7.15 - 2022-11-02
|
||||
|
||||
### Fixed
|
||||
- You can no longer set the currency of expense and revenue accounts.
|
||||
@ -181,6 +209,32 @@ Please refer to the [documentation](https://docs.firefly-iii.org/firefly-iii/) a
|
||||
- [Issue 4013](https://github.com/firefly-iii/firefly-iii/issues/4013) Date in email message was not localized.
|
||||
- [Issue 5949](https://github.com/firefly-iii/firefly-iii/issues/5949) Deleting a transaction would sometimes send you back to a 404.
|
||||
|
||||
## x.x.x - 20xx-xx-xx
|
||||
|
||||
### Added
|
||||
- Initial release.
|
||||
|
||||
### Changed
|
||||
- Initial release.
|
||||
|
||||
### Deprecated
|
||||
- Initial release.
|
||||
|
||||
### Removed
|
||||
- Initial release.
|
||||
|
||||
### Fixed
|
||||
- Initial release.
|
||||
|
||||
### Security
|
||||
- Initial release.
|
||||
|
||||
### API
|
||||
- Initial release.
|
||||
|
||||
|
||||
# Full change log
|
||||
|
||||
Can be found here: https://docs.firefly-iii.org/firefly-iii/about-firefly-iii/changelog/
|
||||
|
||||
|
||||
|
@ -91,7 +91,7 @@
|
||||
"laravel/framework": "^9",
|
||||
"laravel/passport": "11.*",
|
||||
"laravel/sanctum": "^3.0",
|
||||
"laravel/ui": "^4.0",
|
||||
"laravel/ui": "^4.1",
|
||||
"laravelcollective/html": "6.*",
|
||||
"league/commonmark": "2.*",
|
||||
"league/csv": "^9.7",
|
||||
@ -100,7 +100,7 @@
|
||||
"pragmarx/google2fa": "^8.0",
|
||||
"predis/predis": "^2.0",
|
||||
"psr/log": "<4",
|
||||
"ramsey/uuid": "^4.5",
|
||||
"ramsey/uuid": "^4.6",
|
||||
"rcrowe/twigbridge": "^0.14",
|
||||
"spatie/data-transfer-object": "^3.9",
|
||||
"spatie/laravel-ignition": "^1.5",
|
||||
|
593
composer.lock
generated
593
composer.lock
generated
File diff suppressed because it is too large
Load Diff
@ -101,7 +101,7 @@ return [
|
||||
'webhooks' => false,
|
||||
'handle_debts' => true,
|
||||
],
|
||||
'version' => '5.7.15',
|
||||
'version' => '5.7.16',
|
||||
'api_version' => '1.5.6',
|
||||
'db_version' => 18,
|
||||
|
||||
|
63
config/passport.php
Normal file
63
config/passport.php
Normal file
@ -0,0 +1,63 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
return [
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Passport Guard
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Here you may specify which authentication guard Passport will use when
|
||||
| authenticating users. This value should correspond with one of your
|
||||
| guards that is already present in your "auth" configuration file.
|
||||
|
|
||||
*/
|
||||
|
||||
'guard' => envNonEmpty('AUTHENTICATION_GUARD', 'web'),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Encryption Keys
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Passport uses encryption keys while generating secure access tokens for
|
||||
| your application. By default, the keys are stored as local files but
|
||||
| can be set via environment variables when that is more convenient.
|
||||
|
|
||||
*/
|
||||
|
||||
'private_key' => env('PASSPORT_PRIVATE_KEY'),
|
||||
|
||||
'public_key' => env('PASSPORT_PUBLIC_KEY'),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Client UUIDs
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| By default, Passport uses auto-incrementing primary keys when assigning
|
||||
| IDs to clients. However, if Passport is installed using the provided
|
||||
| --uuids switch, this will be set to "true" and UUIDs will be used.
|
||||
|
|
||||
*/
|
||||
|
||||
'client_uuids' => false,
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Personal Access Client
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| If you enable client hashing, you should set the personal access client
|
||||
| ID and unhashed secret within your environment file. The values will
|
||||
| get used while issuing fresh personal access tokens to your users.
|
||||
|
|
||||
*/
|
||||
|
||||
'personal_access_client' => [
|
||||
'id' => env('PASSPORT_PERSONAL_ACCESS_CLIENT_ID'),
|
||||
'secret' => env('PASSPORT_PERSONAL_ACCESS_CLIENT_SECRET'),
|
||||
],
|
||||
|
||||
];
|
@ -229,5 +229,6 @@ return [
|
||||
'attachment_notes_start' => ['alias' => true, 'alias_for' => 'attachment_notes_starts', 'needs_context' => true],
|
||||
'attachment_notes_ends' => ['alias' => false, 'needs_context' => true],
|
||||
'attachment_notes_end' => ['alias' => true, 'alias_for' => 'attachment_notes_ends', 'needs_context' => true],
|
||||
'sepa_ct_is' => ['alias' => false, 'needs_context' => true],
|
||||
],
|
||||
];
|
||||
|
@ -17,7 +17,7 @@
|
||||
"axios-cache-adapter": "^2.7.3",
|
||||
"core-js": "^3.6.5",
|
||||
"date-fns": "^2.28.0",
|
||||
"quasar": "^2.7.1",
|
||||
"quasar": "^2.11.1",
|
||||
"vue": "3",
|
||||
"vue-i18n": "^9.0.0",
|
||||
"vue-router": "^4.0.0",
|
||||
|
6
frontend/src/i18n/bg_BG/index.js
vendored
6
frontend/src/i18n/bg_BG/index.js
vendored
@ -69,9 +69,9 @@ export default {
|
||||
"new_budget": "\u041d\u043e\u0432 \u0431\u044e\u0434\u0436\u0435\u0442",
|
||||
"new_asset_account": "\u041d\u043e\u0432\u0430 \u0441\u043c\u0435\u0442\u043a\u0430 \u0437\u0430 \u0430\u043a\u0442\u0438\u0432\u0438",
|
||||
"newTransfer": "\u041d\u043e\u0432\u043e \u043f\u0440\u0435\u0445\u0432\u044a\u0440\u043b\u044f\u043d\u0435",
|
||||
"submission_options": "(firefly.submission_options)",
|
||||
"apply_rules_checkbox": "(firefly.apply_rules_checkbox)",
|
||||
"fire_webhooks_checkbox": "(firefly.fire_webhooks_checkbox)",
|
||||
"submission_options": "Submission options",
|
||||
"apply_rules_checkbox": "Apply rules",
|
||||
"fire_webhooks_checkbox": "Fire webhooks",
|
||||
"newDeposit": "\u041d\u043e\u0432 \u0434\u0435\u043f\u043e\u0437\u0438\u0442",
|
||||
"newWithdrawal": "\u041d\u043e\u0432 \u0440\u0430\u0437\u0445\u043e\u0434",
|
||||
"bills_paid": "\u041f\u043b\u0430\u0442\u0435\u043d\u0438 \u0441\u043c\u0435\u0442\u043a\u0438",
|
||||
|
6
frontend/src/i18n/cs_CZ/index.js
vendored
6
frontend/src/i18n/cs_CZ/index.js
vendored
@ -69,9 +69,9 @@ export default {
|
||||
"new_budget": "Nov\u00fd rozpo\u010det",
|
||||
"new_asset_account": "Nov\u00fd \u00fa\u010det s aktivy",
|
||||
"newTransfer": "Nov\u00fd p\u0159evod",
|
||||
"submission_options": "(firefly.submission_options)",
|
||||
"apply_rules_checkbox": "(firefly.apply_rules_checkbox)",
|
||||
"fire_webhooks_checkbox": "(firefly.fire_webhooks_checkbox)",
|
||||
"submission_options": "Submission options",
|
||||
"apply_rules_checkbox": "Apply rules",
|
||||
"fire_webhooks_checkbox": "Fire webhooks",
|
||||
"newDeposit": "Nov\u00fd vklad",
|
||||
"newWithdrawal": "Nov\u00fd v\u00fddaj",
|
||||
"bills_paid": "Zaplacen\u00e9 \u00fa\u010dty",
|
||||
|
6
frontend/src/i18n/da_DK/index.js
vendored
6
frontend/src/i18n/da_DK/index.js
vendored
@ -69,9 +69,9 @@ export default {
|
||||
"new_budget": "Nyt budget",
|
||||
"new_asset_account": "Ny aktivkonto",
|
||||
"newTransfer": "New transfer",
|
||||
"submission_options": "(firefly.submission_options)",
|
||||
"apply_rules_checkbox": "(firefly.apply_rules_checkbox)",
|
||||
"fire_webhooks_checkbox": "(firefly.fire_webhooks_checkbox)",
|
||||
"submission_options": "Submission options",
|
||||
"apply_rules_checkbox": "Apply rules",
|
||||
"fire_webhooks_checkbox": "Fire webhooks",
|
||||
"newDeposit": "New deposit",
|
||||
"newWithdrawal": "New expense",
|
||||
"bills_paid": "Betalte regninger",
|
||||
|
30
frontend/src/i18n/de_DE/index.js
vendored
30
frontend/src/i18n/de_DE/index.js
vendored
@ -69,9 +69,9 @@ export default {
|
||||
"new_budget": "Neues Budget",
|
||||
"new_asset_account": "Neues Bestandskonto",
|
||||
"newTransfer": "Neue Umbuchung",
|
||||
"submission_options": "(firefly.submission_options)",
|
||||
"apply_rules_checkbox": "(firefly.apply_rules_checkbox)",
|
||||
"fire_webhooks_checkbox": "(firefly.fire_webhooks_checkbox)",
|
||||
"submission_options": "Submission options",
|
||||
"apply_rules_checkbox": "Apply rules",
|
||||
"fire_webhooks_checkbox": "Fire webhooks",
|
||||
"newDeposit": "Neue Einnahme",
|
||||
"newWithdrawal": "Neue Ausgabe",
|
||||
"bills_paid": "Rechnungen bezahlt",
|
||||
@ -80,13 +80,13 @@ export default {
|
||||
"budgeted": "Vorgesehen",
|
||||
"spent": "Ausgegeben",
|
||||
"no_bill": "(keine Belege)",
|
||||
"rule_trigger_source_account_starts_choice": "Name des Quellkontos beginnt mit..",
|
||||
"rule_trigger_source_account_starts_choice": "Quellkonto-Name beginnt mit..",
|
||||
"rule_trigger_source_account_ends_choice": "Quellkonto-Name endet mit..",
|
||||
"rule_trigger_source_account_is_choice": "Quellkonto-Name lautet..",
|
||||
"rule_trigger_source_account_contains_choice": "Quellkonto-Name enh\u00e4lt..",
|
||||
"rule_trigger_account_id_choice": "Beide Konto IDs sind exakt..",
|
||||
"rule_trigger_source_account_id_choice": "Quellkonto ID ist genau..",
|
||||
"rule_trigger_destination_account_id_choice": "Zielkonto ID ist genau..",
|
||||
"rule_trigger_source_account_id_choice": "Quellkonto-ID ist genau..",
|
||||
"rule_trigger_destination_account_id_choice": "Zielkonto-ID ist genau..",
|
||||
"rule_trigger_account_is_cash_choice": "Beide Konten sind Bargeld",
|
||||
"rule_trigger_source_is_cash_choice": "Quellkonto ist (bar)",
|
||||
"rule_trigger_destination_is_cash_choice": "Zielkonto ist (bar)",
|
||||
@ -100,8 +100,8 @@ export default {
|
||||
"rule_trigger_destination_account_contains_choice": "Zielkonto-Name enth\u00e4lt..",
|
||||
"rule_trigger_destination_account_nr_starts_choice": "Zielkontonummer\/IBAN beginnt mit..",
|
||||
"rule_trigger_destination_account_nr_ends_choice": "Zielkontonummer\/IBAN endet auf..",
|
||||
"rule_trigger_destination_account_nr_is_choice": "Zielkontonummer\/IBAN ist..",
|
||||
"rule_trigger_destination_account_nr_contains_choice": "Zielkontonummer\/IBAN enth\u00e4lt..",
|
||||
"rule_trigger_destination_account_nr_is_choice": "Zielkontonummer \/ IBAN ist..",
|
||||
"rule_trigger_destination_account_nr_contains_choice": "Zielkontonummer \/ IBAN enth\u00e4lt..",
|
||||
"rule_trigger_transaction_type_choice": "Buchung ist vom Typ..",
|
||||
"rule_trigger_category_is_choice": "Kategorie ist..",
|
||||
"rule_trigger_amount_less_choice": "Betrag ist geringer als..",
|
||||
@ -142,10 +142,10 @@ export default {
|
||||
"rule_trigger_any_external_url_choice": "Buchung hat eine externe URL",
|
||||
"rule_trigger_no_external_url_choice": "Buchung hat keine externe URL",
|
||||
"rule_trigger_id_choice": "Buchungskennung lautet \u2026",
|
||||
"rule_action_delete_transaction_choice": "DELETE transaction(!)",
|
||||
"rule_action_set_category_choice": "Set category to ..",
|
||||
"rule_action_delete_transaction_choice": "Buchung L\u00d6SCHEN(!)",
|
||||
"rule_action_set_category_choice": "Kategorie zuweisen\u00a0...",
|
||||
"rule_action_clear_category_choice": "Bereinige jede Kategorie",
|
||||
"rule_action_set_budget_choice": "Set budget to ..",
|
||||
"rule_action_set_budget_choice": "Setze Budget auf ..",
|
||||
"rule_action_clear_budget_choice": "Alle Budgets leeren",
|
||||
"rule_action_add_tag_choice": "Add tag ..",
|
||||
"rule_action_remove_tag_choice": "Remove tag ..",
|
||||
@ -154,13 +154,13 @@ export default {
|
||||
"rule_action_update_piggy_choice": "Add \/ remove transaction amount in piggy bank ..",
|
||||
"rule_action_append_description_choice": "Append description with ..",
|
||||
"rule_action_prepend_description_choice": "Prepend description with ..",
|
||||
"rule_action_set_source_account_choice": "Set source account to ..",
|
||||
"rule_action_set_destination_account_choice": "Set destination account to ..",
|
||||
"rule_action_set_source_account_choice": "Quellkonto festlegen auf ..",
|
||||
"rule_action_set_destination_account_choice": "Zielkonto festlegen auf ..",
|
||||
"rule_action_append_notes_choice": "Append notes with ..",
|
||||
"rule_action_prepend_notes_choice": "Prepend notes with ..",
|
||||
"rule_action_clear_notes_choice": "Alle Notizen entfernen",
|
||||
"rule_action_set_notes_choice": "Set notes to ..",
|
||||
"rule_action_link_to_bill_choice": "Link to a bill ..",
|
||||
"rule_action_set_notes_choice": "Setze Notizen auf ..",
|
||||
"rule_action_link_to_bill_choice": "Mit einer Rechnung verkn\u00fcpfen..",
|
||||
"rule_action_convert_deposit_choice": "Buchung in eine Einzahlung umwandeln",
|
||||
"rule_action_convert_withdrawal_choice": "Buchung in eine Ausgabe umwandeln",
|
||||
"rule_action_convert_transfer_choice": "Buchung in eine Umbuchung umwandeln",
|
||||
|
6
frontend/src/i18n/el_GR/index.js
vendored
6
frontend/src/i18n/el_GR/index.js
vendored
@ -69,9 +69,9 @@ export default {
|
||||
"new_budget": "\u039d\u03ad\u03bf\u03c2 \u03c0\u03c1\u03bf\u03cb\u03c0\u03bf\u03bb\u03bf\u03b3\u03b9\u03c3\u03bc\u03cc\u03c2",
|
||||
"new_asset_account": "\u039d\u03ad\u03bf\u03c2 \u03bb\u03bf\u03b3\u03b1\u03c1\u03b9\u03b1\u03c3\u03bc\u03cc\u03c2 \u03ba\u03b5\u03c6\u03b1\u03bb\u03b1\u03af\u03bf\u03c5",
|
||||
"newTransfer": "\u039d\u03ad\u03b1 \u03bc\u03b5\u03c4\u03b1\u03c6\u03bf\u03c1\u03ac",
|
||||
"submission_options": "(firefly.submission_options)",
|
||||
"apply_rules_checkbox": "(firefly.apply_rules_checkbox)",
|
||||
"fire_webhooks_checkbox": "(firefly.fire_webhooks_checkbox)",
|
||||
"submission_options": "Submission options",
|
||||
"apply_rules_checkbox": "Apply rules",
|
||||
"fire_webhooks_checkbox": "Fire webhooks",
|
||||
"newDeposit": "\u039d\u03ad\u03b1 \u03ba\u03b1\u03c4\u03ac\u03b8\u03b5\u03c3\u03b7",
|
||||
"newWithdrawal": "\u039d\u03ad\u03b1 \u03b4\u03b1\u03c0\u03ac\u03bd\u03b7",
|
||||
"bills_paid": "\u03a0\u03bb\u03b7\u03c1\u03c9\u03bc\u03ad\u03bd\u03b1 \u03c0\u03ac\u03b3\u03b9\u03b1 \u03ad\u03be\u03bf\u03b4\u03b1",
|
||||
|
6
frontend/src/i18n/en_GB/index.js
vendored
6
frontend/src/i18n/en_GB/index.js
vendored
@ -69,9 +69,9 @@ export default {
|
||||
"new_budget": "New budget",
|
||||
"new_asset_account": "New asset account",
|
||||
"newTransfer": "New transfer",
|
||||
"submission_options": "(firefly.submission_options)",
|
||||
"apply_rules_checkbox": "(firefly.apply_rules_checkbox)",
|
||||
"fire_webhooks_checkbox": "(firefly.fire_webhooks_checkbox)",
|
||||
"submission_options": "Submission options",
|
||||
"apply_rules_checkbox": "Apply rules",
|
||||
"fire_webhooks_checkbox": "Fire webhooks",
|
||||
"newDeposit": "New deposit",
|
||||
"newWithdrawal": "New expense",
|
||||
"bills_paid": "Bills paid",
|
||||
|
6
frontend/src/i18n/es_ES/index.js
vendored
6
frontend/src/i18n/es_ES/index.js
vendored
@ -69,9 +69,9 @@ export default {
|
||||
"new_budget": "Nuevo presupuesto",
|
||||
"new_asset_account": "Nueva cuenta de activo",
|
||||
"newTransfer": "Nueva transferencia",
|
||||
"submission_options": "(firefly.submission_options)",
|
||||
"apply_rules_checkbox": "(firefly.apply_rules_checkbox)",
|
||||
"fire_webhooks_checkbox": "(firefly.fire_webhooks_checkbox)",
|
||||
"submission_options": "Submission options",
|
||||
"apply_rules_checkbox": "Apply rules",
|
||||
"fire_webhooks_checkbox": "Fire webhooks",
|
||||
"newDeposit": "Nuevo deposito",
|
||||
"newWithdrawal": "Nuevo gasto",
|
||||
"bills_paid": "Facturas pagadas",
|
||||
|
6
frontend/src/i18n/fi_FI/index.js
vendored
6
frontend/src/i18n/fi_FI/index.js
vendored
@ -69,9 +69,9 @@ export default {
|
||||
"new_budget": "Uusi budjetti",
|
||||
"new_asset_account": "Uusi omaisuustili",
|
||||
"newTransfer": "Uusi siirto",
|
||||
"submission_options": "(firefly.submission_options)",
|
||||
"apply_rules_checkbox": "(firefly.apply_rules_checkbox)",
|
||||
"fire_webhooks_checkbox": "(firefly.fire_webhooks_checkbox)",
|
||||
"submission_options": "Submission options",
|
||||
"apply_rules_checkbox": "Apply rules",
|
||||
"fire_webhooks_checkbox": "Fire webhooks",
|
||||
"newDeposit": "Uusi talletus",
|
||||
"newWithdrawal": "Uusi kustannus",
|
||||
"bills_paid": "Maksetut laskut",
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user