mirror of
https://github.com/firefly-iii/firefly-iii.git
synced 2025-10-14 00:04:24 +00:00
Compare commits
155 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
4daaa44ba8 | ||
|
c3e739cd6f | ||
|
851da6a0a1 | ||
|
a99f68fd17 | ||
|
1266eff7f6 | ||
|
0429f50e5c | ||
|
e9e0225731 | ||
|
3c1f44f554 | ||
|
b0b65c3f04 | ||
|
fe724fa1b8 | ||
|
c3ce9e896e | ||
|
c60120ac20 | ||
|
8bbe519350 | ||
|
c426ff352c | ||
|
15605dd163 | ||
|
f2499e0a77 | ||
|
b5734beb32 | ||
|
ed4d2ee6ad | ||
|
6249488f0f | ||
|
29bd3a2804 | ||
|
ba35c5da0b | ||
|
9b242f1a75 | ||
|
1acc2ab18b | ||
|
3666ef8c59 | ||
|
e4db21f0c0 | ||
|
d40fd485ca | ||
|
32e89155a0 | ||
|
5e654786be | ||
|
75ce777090 | ||
|
f350948fb2 | ||
|
1f4ca9c8fe | ||
|
e468d5b892 | ||
|
89ab62fff2 | ||
|
bdf7d3978f | ||
|
a4f3be5397 | ||
|
265d973811 | ||
|
e22ed9a69b | ||
|
fcecd5c85e | ||
|
2780cf4b20 | ||
|
7e63700ca2 | ||
|
2d9a3f5fc6 | ||
|
f5bbd445d2 | ||
|
12008fb0e9 | ||
|
5f6c84ab4c | ||
|
63184ac298 | ||
|
5f6772260d | ||
|
22a237d316 | ||
|
c47980a737 | ||
|
e43372b2ce | ||
|
395b6ecb76 | ||
|
328a1e256e | ||
|
4a31f9ce7e | ||
|
345f4903a9 | ||
|
3fe5e5ea8c | ||
|
b0da22ddf2 | ||
|
388ee14dfc | ||
|
2c53c72024 | ||
|
de260adca4 | ||
|
d8813120a7 | ||
|
989fd1adba | ||
|
a5f4793e81 | ||
|
86243131cd | ||
|
344cbe4fb7 | ||
|
44af5473a8 | ||
|
f33f9c797b | ||
|
352eedb136 | ||
|
c8d6ef3782 | ||
|
922a5fa9c7 | ||
|
c125984d55 | ||
|
a60c3165f1 | ||
|
363c849c50 | ||
|
36c9782c8f | ||
|
49847a91e3 | ||
|
516653d007 | ||
|
2743359a4e | ||
|
8055e9e927 | ||
|
702f2c3146 | ||
|
ad36082fca | ||
|
81e650986d | ||
|
f3c89e8055 | ||
|
3a8c0074b7 | ||
|
dcfcbfd9b5 | ||
|
04c71a2e9e | ||
|
2383d16e7a | ||
|
5bb7705702 | ||
|
2e3267ab9e | ||
|
d969cd72c0 | ||
|
e4894c756a | ||
|
f52044e794 | ||
|
43960a5b60 | ||
|
81b0b048db | ||
|
3278d9850e | ||
|
b13bcec61a | ||
|
21d18acabc | ||
|
4060d14de0 | ||
|
c67a71e238 | ||
|
ed330e30d0 | ||
|
7673d11673 | ||
|
e1114f720d | ||
|
b49e7d6b21 | ||
|
c9ba5f08c4 | ||
|
5aa8793e33 | ||
|
dd98549bce | ||
|
d6d53cc598 | ||
|
6516495e2b | ||
|
7fcdf85dee | ||
|
704c6055b3 | ||
|
f650dd9463 | ||
|
1b261359e6 | ||
|
8050c8cb84 | ||
|
7666960a86 | ||
|
0a7210729f | ||
|
90c9fdaf55 | ||
|
d55833cb86 | ||
|
39fbf3ce20 | ||
|
15994c8c56 | ||
|
b942f351f8 | ||
|
e05c174e6d | ||
|
05d461fb88 | ||
|
7bb2f96ae2 | ||
|
8f15bd716d | ||
|
0c6e00666b | ||
|
5ba079e71c | ||
|
b36f6741ff | ||
|
d7bbc8334e | ||
|
2b7101e362 | ||
|
e74b629dc2 | ||
|
a4f329cfc3 | ||
|
e993abc8fb | ||
|
6961365a40 | ||
|
16303515f5 | ||
|
bb5bca9cf0 | ||
|
e8a61821e9 | ||
|
5d4cf5f55e | ||
|
5e9de60c1a | ||
|
417700ef13 | ||
|
b14062b197 | ||
|
a3b4d5ff62 | ||
|
6b7fc03f02 | ||
|
b60a3be34b | ||
|
83b8fdba05 | ||
|
0b64507fd7 | ||
|
45dcd5df09 | ||
|
3bdea43744 | ||
|
b3895a04a0 | ||
|
d4738b21ab | ||
|
2f66315416 | ||
|
abdb717b37 | ||
|
f7b66a048a | ||
|
a91f6fbfaf | ||
|
f3566c609a | ||
|
904320b9b8 | ||
|
35c1ce6504 | ||
|
ddefdd5ec5 | ||
|
fd37054493 |
14
.env.example
14
.env.example
@@ -12,6 +12,9 @@ SITE_OWNER=mail@example.com
|
||||
# The encryption key for your sessions. Keep this very secure.
|
||||
# Change it to a string of exactly 32 chars or use something like `php artisan key:generate` to generate it.
|
||||
# If you use Docker or similar, you can set this variable from a file by using APP_KEY_FILE
|
||||
#
|
||||
# Avoid the "#" character in your APP_KEY, it may break things.
|
||||
#
|
||||
APP_KEY=SomeRandomStringOf32CharsExactly
|
||||
|
||||
# Firefly III will launch using this language (for new users and unauthenticated visitors)
|
||||
@@ -192,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
|
||||
#
|
||||
@@ -233,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.
|
||||
|
||||
|
1
.github/workflows/build.yml
vendored
1
.github/workflows/build.yml
vendored
@@ -4,6 +4,7 @@ on:
|
||||
branches:
|
||||
- main
|
||||
- develop
|
||||
- 5.8-dev
|
||||
pull_request:
|
||||
types: [opened, synchronize, reopened]
|
||||
jobs:
|
||||
|
3
.github/workflows/stale.yml
vendored
3
.github/workflows/stale.yml
vendored
@@ -2,6 +2,7 @@ name: "Close stale issues"
|
||||
on:
|
||||
schedule:
|
||||
- cron: "30 1 * * *"
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
@@ -13,7 +14,7 @@ jobs:
|
||||
pull-requests: write # for actions/stale to close stale PRs
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/stale@v3
|
||||
- uses: actions/stale@v6
|
||||
with:
|
||||
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
stale-issue-message: >
|
||||
|
1
.gitignore
vendored
1
.gitignore
vendored
@@ -6,3 +6,4 @@
|
||||
npm-debug.log
|
||||
yarn-error.log
|
||||
.env
|
||||
/.ci/php-cs-fixer/vendor
|
||||
|
@@ -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);
|
||||
}
|
||||
|
@@ -97,8 +97,6 @@ class DestroyController extends Controller
|
||||
|
||||
$this->groupRepository->destroy($transactionGroup);
|
||||
|
||||
// trigger just after destruction
|
||||
event(new DestroyedTransactionGroup($transactionGroup));
|
||||
app('preferences')->mark();
|
||||
|
||||
/** @var Account $account */
|
||||
@@ -124,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',
|
||||
];
|
||||
}
|
||||
|
||||
|
@@ -85,7 +85,7 @@ class UpdateRequest extends FormRequest
|
||||
'notes',
|
||||
];
|
||||
|
||||
$this->floatFields = [
|
||||
$this->floatFields = [ // not really floats, for validation.
|
||||
'amount',
|
||||
'foreign_amount',
|
||||
];
|
||||
@@ -406,8 +406,7 @@ class UpdateRequest extends FormRequest
|
||||
if (array_key_exists($fieldName, $transaction)) {
|
||||
$value = $transaction[$fieldName];
|
||||
if (is_float($value)) {
|
||||
// TODO this effectively limits the max number of decimals in currencies to 14.
|
||||
$current[$fieldName] = sprintf('%.14f', $value);
|
||||
$current[$fieldName] = sprintf('%.24f', $value);
|
||||
}
|
||||
if (!is_float($value)) {
|
||||
$current[$fieldName] = (string) $value;
|
||||
|
@@ -47,7 +47,7 @@ class PreferenceStoreRequest extends FormRequest
|
||||
$array['data'] = false;
|
||||
}
|
||||
if (is_numeric($array['data'])) {
|
||||
$array['data'] = (float) $array['data'];
|
||||
$array['data'] = (float) $array['data']; // intentional float.
|
||||
}
|
||||
|
||||
return $array;
|
||||
|
@@ -48,7 +48,7 @@ class PreferenceUpdateRequest extends FormRequest
|
||||
$array['data'] = false;
|
||||
}
|
||||
if (is_numeric($array['data'])) {
|
||||
$array['data'] = (float) $array['data'];
|
||||
$array['data'] = (float) $array['data']; // intentional float.
|
||||
}
|
||||
|
||||
return $array;
|
||||
|
@@ -61,6 +61,7 @@ class CorrectDatabase extends Command
|
||||
'firefly-iii:create-link-types',
|
||||
'firefly-iii:create-access-tokens',
|
||||
'firefly-iii:remove-bills',
|
||||
'firefly-iii:fix-negative-limits',
|
||||
'firefly-iii:enable-currencies',
|
||||
'firefly-iii:fix-transfer-budgets',
|
||||
'firefly-iii:fix-uneven-amount',
|
||||
|
67
app/Console/Commands/Correction/FixBudgetLimits.php
Normal file
67
app/Console/Commands/Correction/FixBudgetLimits.php
Normal file
@@ -0,0 +1,67 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* FixBudgetLimits.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/>.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Console\Commands\Correction;
|
||||
|
||||
use DB;
|
||||
use FireflyIII\Models\BudgetLimit;
|
||||
use Illuminate\Console\Command;
|
||||
|
||||
/**
|
||||
* Class CorrectionSkeleton
|
||||
*/
|
||||
class FixBudgetLimits extends Command
|
||||
{
|
||||
/**
|
||||
* The console command description.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'Fixes negative budget limits';
|
||||
/**
|
||||
* The name and signature of the console command.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'firefly-iii:fix-negative-limits';
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function handle(): int
|
||||
{
|
||||
$set = BudgetLimit::where('amount', '<', '0')->get();
|
||||
if (0 === $set->count()) {
|
||||
$this->info('All budget limits are OK.');
|
||||
return 0;
|
||||
}
|
||||
$count = BudgetLimit::where('amount', '<', '0')->update(['amount' => DB::raw('amount * -1')]);
|
||||
|
||||
$this->info(sprintf('Fixed %d budget limit(s)', $count));
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
@@ -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)));
|
||||
|
@@ -82,6 +82,7 @@ class UpgradeDatabase extends Command
|
||||
'firefly-iii:create-link-types',
|
||||
'firefly-iii:create-access-tokens',
|
||||
'firefly-iii:remove-bills',
|
||||
'firefly-iii:fix-negative-limits',
|
||||
'firefly-iii:enable-currencies',
|
||||
'firefly-iii:fix-transfer-budgets',
|
||||
'firefly-iii:fix-uneven-amount',
|
||||
|
61
app/Events/ChangedPiggyBankAmount.php
Normal file
61
app/Events/ChangedPiggyBankAmount.php
Normal file
@@ -0,0 +1,61 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* ChangedPiggyBankAmount.php
|
||||
* Copyright (c) 2023 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/>.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
@@ -288,18 +288,27 @@ class AccountFactory
|
||||
$fields = $this->validCCFields;
|
||||
}
|
||||
|
||||
// remove currency_id if necessary.
|
||||
$type = $account->accountType->type;
|
||||
$list = config('firefly.valid_currency_account_types');
|
||||
if (!in_array($type, $list, true)) {
|
||||
$pos = array_search('currency_id', $fields);
|
||||
if ($pos !== false) {
|
||||
unset($fields[$pos]);
|
||||
}
|
||||
}
|
||||
|
||||
/** @var AccountMetaFactory $factory */
|
||||
$factory = app(AccountMetaFactory::class);
|
||||
foreach ($fields as $field) {
|
||||
// if the field is set but NULL, skip it.
|
||||
// if the field is set but "", update it.
|
||||
if (array_key_exists($field, $data) && null !== $data[$field]) {
|
||||
|
||||
// convert boolean value:
|
||||
if (is_bool($data[$field]) && false === $data[$field]) {
|
||||
$data[$field] = 0;
|
||||
}
|
||||
if (is_bool($data[$field]) && true === $data[$field]) {
|
||||
if (true === $data[$field]) {
|
||||
$data[$field] = 1;
|
||||
}
|
||||
|
||||
|
@@ -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;
|
||||
|
72
app/Handlers/Events/PiggyBankEventHandler.php
Normal file
72
app/Handlers/Events/PiggyBankEventHandler.php
Normal file
@@ -0,0 +1,72 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* PiggyBankEventHandler.php
|
||||
* Copyright (c) 2023 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/>.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
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,16 +150,19 @@ 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 (-1 === bccomp($amount, '0')) {
|
||||
$amount = bcmul($amount, '-1');
|
||||
}
|
||||
|
||||
if (null !== $limit) {
|
||||
$limit->amount = $amount;
|
||||
@@ -169,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,
|
||||
@@ -184,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']);
|
||||
|
||||
@@ -198,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);
|
||||
@@ -223,9 +226,12 @@ 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 (-1 === bccomp($amount, '0')) {
|
||||
$amount = bcmul($amount, '-1');
|
||||
}
|
||||
|
||||
$limit = $this->blRepository->update($budgetLimit, ['amount' => $amount]);
|
||||
$array = $limit->toArray();
|
||||
@@ -240,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);
|
||||
|
@@ -40,10 +40,8 @@ use Illuminate\View\View;
|
||||
*/
|
||||
class EditController extends Controller
|
||||
{
|
||||
/** @var AttachmentHelperInterface Helper for attachments. */
|
||||
private $attachments;
|
||||
/** @var BudgetRepositoryInterface The budget repository */
|
||||
private $repository;
|
||||
private AttachmentHelperInterface $attachments;
|
||||
private BudgetRepositoryInterface $repository;
|
||||
|
||||
/**
|
||||
* EditController constructor.
|
||||
@@ -56,7 +54,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 +67,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 +117,8 @@ class EditController extends Controller
|
||||
/**
|
||||
* Budget update routine.
|
||||
*
|
||||
* @param BudgetFormUpdateRequest $request
|
||||
* @param Budget $budget
|
||||
* @param BudgetFormUpdateRequest $request
|
||||
* @param Budget $budget
|
||||
*
|
||||
* @return RedirectResponse
|
||||
*/
|
||||
@@ -129,7 +127,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 +139,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,
|
||||
];
|
||||
}
|
||||
|
@@ -31,7 +31,6 @@ use FireflyIII\Repositories\Bill\BillRepositoryInterface;
|
||||
use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface;
|
||||
use FireflyIII\Support\CacheProperties;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use JsonException;
|
||||
|
||||
/**
|
||||
* Class BillController.
|
||||
@@ -134,7 +133,7 @@ class BillController extends Controller
|
||||
}
|
||||
);
|
||||
|
||||
$chartData = [
|
||||
$chartData = [
|
||||
['type' => 'line', 'label' => (string) trans('firefly.min-amount'), 'currency_symbol' => $bill->transactionCurrency->symbol,
|
||||
'currency_code' => $bill->transactionCurrency->code, 'entries' => []],
|
||||
['type' => 'line', 'label' => (string) trans('firefly.max-amount'), 'currency_symbol' => $bill->transactionCurrency->symbol,
|
||||
@@ -142,7 +141,7 @@ class BillController extends Controller
|
||||
['type' => 'bar', 'label' => (string) trans('firefly.journal-amount'), 'currency_symbol' => $bill->transactionCurrency->symbol,
|
||||
'currency_code' => $bill->transactionCurrency->code, 'entries' => []],
|
||||
];
|
||||
|
||||
$currencyId = (int) $bill->transaction_currency_id;
|
||||
foreach ($journals as $journal) {
|
||||
$date = $journal['date']->isoFormat((string) trans('config.month_and_day_js', [], $locale));
|
||||
$chartData[0]['entries'][$date] = $bill->amount_min; // minimum amount of bill
|
||||
@@ -152,7 +151,12 @@ class BillController extends Controller
|
||||
if (!array_key_exists($date, $chartData[2]['entries'])) {
|
||||
$chartData[2]['entries'][$date] = '0';
|
||||
}
|
||||
$amount = bcmul($journal['amount'], '-1');
|
||||
$amount = bcmul($journal['amount'], '-1');
|
||||
if ($currencyId === $journal['foreign_currency_id']) {
|
||||
$amount = bcmul($journal['foreign_amount'], '-1');
|
||||
}
|
||||
|
||||
|
||||
$chartData[2]['entries'][$date] = bcadd($chartData[2]['entries'][$date], $amount); // amount of journal
|
||||
}
|
||||
|
||||
|
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -542,7 +542,7 @@ class TagController 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'),
|
||||
|
@@ -93,6 +93,7 @@ class InstallController extends Controller
|
||||
'firefly-iii:create-link-types' => [],
|
||||
'firefly-iii:create-access-tokens' => [],
|
||||
'firefly-iii:remove-bills' => [],
|
||||
'firefly-iii:fix-negative-limits' => [],
|
||||
'firefly-iii:enable-currencies' => [],
|
||||
'firefly-iii:fix-transfer-budgets' => [],
|
||||
'firefly-iii:fix-uneven-amount' => [],
|
||||
|
@@ -23,6 +23,7 @@ declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Http\Controllers\Transaction;
|
||||
|
||||
use FireflyIII\Events\UpdatedTransactionGroup;
|
||||
use FireflyIII\Http\Controllers\Controller;
|
||||
use FireflyIII\Http\Requests\BulkEditJournalRequest;
|
||||
use FireflyIII\Models\TransactionJournal;
|
||||
@@ -32,6 +33,7 @@ use Illuminate\Contracts\Foundation\Application;
|
||||
use Illuminate\Contracts\View\Factory;
|
||||
use Illuminate\Http\RedirectResponse;
|
||||
use Illuminate\Routing\Redirector;
|
||||
use Illuminate\Support\Collection;
|
||||
use Illuminate\View\View;
|
||||
use Log;
|
||||
|
||||
@@ -102,8 +104,8 @@ class BulkController extends Controller
|
||||
$ignoreCategory = 1 === (int) $request->get('ignore_category');
|
||||
$ignoreBudget = 1 === (int) $request->get('ignore_budget');
|
||||
$tagsAction = $request->get('tags_action');
|
||||
|
||||
$count = 0;
|
||||
$collection = new Collection;
|
||||
$count = 0;
|
||||
|
||||
foreach ($journalIds as $journalId) {
|
||||
$journalId = (int) $journalId;
|
||||
@@ -114,9 +116,17 @@ class BulkController extends Controller
|
||||
$resultC = $this->updateJournalCategory($journal, $ignoreCategory, $request->convertString('category'));
|
||||
if ($resultA || $resultB || $resultC) {
|
||||
$count++;
|
||||
$collection->push($journal);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// run rules on changed journals:
|
||||
/** @var TransactionJournal $journal */
|
||||
foreach ($collection as $journal) {
|
||||
event(new UpdatedTransactionGroup($journal->transactionGroup));
|
||||
}
|
||||
|
||||
app('preferences')->mark();
|
||||
$request->session()->flash('success', (string) trans_choice('firefly.mass_edited_transactions_success', $count));
|
||||
|
||||
|
@@ -23,6 +23,7 @@ declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Http\Controllers\Transaction;
|
||||
|
||||
use FireflyIII\Events\DestroyedTransactionGroup;
|
||||
use FireflyIII\Events\UpdatedAccount;
|
||||
use FireflyIII\Http\Controllers\Controller;
|
||||
use FireflyIII\Models\Account;
|
||||
@@ -131,14 +132,12 @@ class DeleteController extends Controller
|
||||
|
||||
$this->repository->destroy($group);
|
||||
|
||||
app('preferences')->mark();
|
||||
|
||||
|
||||
/** @var Account $account */
|
||||
foreach($accounts as $account) {
|
||||
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']);
|
||||
}
|
||||
|
@@ -176,12 +176,14 @@ class Kernel extends HttpKernel
|
||||
CreateFreshApiToken::class,
|
||||
],
|
||||
|
||||
// full API authentication
|
||||
'api' => [
|
||||
EnsureFrontendRequestsAreStateful::class,
|
||||
'auth:api,sanctum',
|
||||
'bindings',
|
||||
],
|
||||
'apiY' => [
|
||||
// do only bindings, no auth
|
||||
'api_basic' => [
|
||||
'bindings',
|
||||
],
|
||||
];
|
||||
|
@@ -29,8 +29,8 @@ use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Auth\AuthenticationException;
|
||||
use Illuminate\Contracts\Auth\Factory as Auth;
|
||||
use Illuminate\Database\QueryException;
|
||||
use Illuminate\Http\Request;
|
||||
use Log;
|
||||
|
||||
/**
|
||||
* Class Authenticate
|
||||
@@ -47,7 +47,7 @@ class Authenticate
|
||||
/**
|
||||
* Create a new middleware instance.
|
||||
*
|
||||
* @param Auth $auth
|
||||
* @param Auth $auth
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
@@ -59,9 +59,9 @@ class Authenticate
|
||||
/**
|
||||
* Handle an incoming request.
|
||||
*
|
||||
* @param Request $request
|
||||
* @param Closure $next
|
||||
* @param string[] ...$guards
|
||||
* @param Request $request
|
||||
* @param Closure $next
|
||||
* @param string[] ...$guards
|
||||
*
|
||||
* @return mixed
|
||||
*
|
||||
@@ -78,8 +78,8 @@ class Authenticate
|
||||
/**
|
||||
* Determine if the user is logged in to any of the given guards.
|
||||
*
|
||||
* @param mixed $request
|
||||
* @param array $guards
|
||||
* @param mixed $request
|
||||
* @param array $guards
|
||||
*
|
||||
* @return mixed
|
||||
* @throws FireflyException
|
||||
@@ -87,21 +87,26 @@ class Authenticate
|
||||
*/
|
||||
protected function authenticate($request, array $guards)
|
||||
{
|
||||
|
||||
if (empty($guards)) {
|
||||
try {
|
||||
// go for default guard:
|
||||
Log::debug(sprintf('Now in %s', __METHOD__));
|
||||
if (0 === count($guards)) {
|
||||
Log::debug('No guards present.');
|
||||
// go for default guard:
|
||||
/** @noinspection PhpUndefinedMethodInspection */
|
||||
if ($this->auth->check()) {
|
||||
Log::debug('Default guard says user is authenticated.');
|
||||
// do an extra check on user object.
|
||||
/** @noinspection PhpUndefinedMethodInspection */
|
||||
if ($this->auth->check()) {
|
||||
|
||||
// do an extra check on user object.
|
||||
/** @noinspection PhpUndefinedMethodInspection */
|
||||
/** @var User $user */
|
||||
$user = $this->auth->authenticate();
|
||||
if (1 === (int) $user->blocked) {
|
||||
$message = (string) trans('firefly.block_account_logout');
|
||||
/** @var User $user */
|
||||
$user = $this->auth->authenticate();
|
||||
if (null === $user) {
|
||||
Log::warning('User is null, throw exception?');
|
||||
}
|
||||
if (null !== $user) {
|
||||
Log::debug(get_class($user));
|
||||
if (1 === (int)$user->blocked) {
|
||||
$message = (string)trans('firefly.block_account_logout');
|
||||
if ('email_changed' === $user->blocked_code) {
|
||||
$message = (string) trans('firefly.email_changed_logout');
|
||||
$message = (string)trans('firefly.email_changed_logout');
|
||||
}
|
||||
app('session')->flash('logoutMessage', $message);
|
||||
/** @noinspection PhpUndefinedMethodInspection */
|
||||
@@ -110,23 +115,16 @@ class Authenticate
|
||||
throw new AuthenticationException('Blocked account.', $guards);
|
||||
}
|
||||
}
|
||||
} catch (QueryException $e) {
|
||||
|
||||
throw new FireflyException(
|
||||
sprintf(
|
||||
'It seems the database has not yet been initialized. Did you run the correct upgrade or installation commands? Error: %s',
|
||||
$e->getMessage()
|
||||
), 0, $e
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
/** @noinspection PhpUndefinedMethodInspection */
|
||||
return $this->auth->authenticate();
|
||||
}
|
||||
|
||||
Log::debug('Guard array is not empty.');
|
||||
|
||||
foreach ($guards as $guard) {
|
||||
Log::debug(sprintf('Now in guard loop, guard is "%s"', $guard));
|
||||
$this->auth->guard($guard)->authenticate();
|
||||
if ($this->auth->guard($guard)->check()) {
|
||||
/** @noinspection PhpVoidFunctionResultUsedInspection */
|
||||
return $this->auth->shouldUse($guard); // @phpstan-ignore-line
|
||||
@@ -134,6 +132,5 @@ class Authenticate
|
||||
}
|
||||
|
||||
throw new AuthenticationException('Unauthenticated.', $guards);
|
||||
|
||||
}
|
||||
}
|
||||
|
@@ -75,7 +75,7 @@ class BudgetFormUpdateRequest extends FormRequest
|
||||
'active' => 'numeric|between:0,1',
|
||||
'auto_budget_type' => 'numeric|integer|gte:0|lte:31',
|
||||
'auto_budget_currency_id' => 'exists:transaction_currencies,id',
|
||||
'auto_budget_amount' => 'min:0|max:1000000000|required_if:auto_budget_type,1|required_if:auto_budget_type,2',
|
||||
'auto_budget_amount' => 'min:0|max:1000000000|required_if:auto_budget_type,1|required_if:auto_budget_type,2|numeric',
|
||||
'auto_budget_period' => 'in:daily,weekly,monthly,quarterly,half_year,yearly',
|
||||
];
|
||||
}
|
||||
|
@@ -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'),
|
||||
|
@@ -99,7 +99,7 @@ class RecurrenceFormRequest extends FormRequest
|
||||
];
|
||||
|
||||
// fill in foreign currency data
|
||||
if (null !== $this->convertFloat('foreign_amount')) {
|
||||
if (null !== $this->convertFloat('foreign_amount')) { // intentional float, used because it defaults to null.
|
||||
$return['transactions'][0]['foreign_amount'] = $this->convertString('foreign_amount');
|
||||
$return['transactions'][0]['foreign_currency_id'] = $this->convertInteger('foreign_currency_id');
|
||||
}
|
||||
@@ -228,7 +228,7 @@ class RecurrenceFormRequest extends FormRequest
|
||||
$rules['repetitions'] = 'required|numeric|between:0,254';
|
||||
}
|
||||
// if foreign amount, currency must be different.
|
||||
if (null !== $this->convertFloat('foreign_amount')) {
|
||||
if (null !== $this->convertFloat('foreign_amount')) { // intentional float, used because it defaults to null.
|
||||
$rules['foreign_currency_id'] = 'exists:transaction_currencies,id|different:transaction_currency_id';
|
||||
}
|
||||
|
||||
|
@@ -1,4 +1,5 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* RuleFormRequest.php
|
||||
* Copyright (c) 2019 james@firefly-iii.org
|
||||
@@ -66,17 +67,48 @@ class RuleFormRequest extends FormRequest
|
||||
if (is_array($triggerData)) {
|
||||
foreach ($triggerData as $trigger) {
|
||||
$stopProcessing = $trigger['stop_processing'] ?? '0';
|
||||
$return[] = [
|
||||
$current = [
|
||||
'type' => $trigger['type'] ?? 'invalid',
|
||||
'value' => $trigger['value'] ?? '',
|
||||
'stop_processing' => 1 === (int) $stopProcessing,
|
||||
'stop_processing' => 1 === (int)$stopProcessing,
|
||||
];
|
||||
$current = self::replaceAmountTrigger($current);
|
||||
|
||||
$return[] = $current;
|
||||
}
|
||||
}
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $array
|
||||
* @return array
|
||||
*/
|
||||
public static function replaceAmountTrigger(array $array): array
|
||||
{
|
||||
// do some sneaky search and replace.
|
||||
$amountFields = [
|
||||
'amount_is',
|
||||
'amount',
|
||||
'amount_exactly',
|
||||
'amount_less',
|
||||
'amount_max',
|
||||
'amount_more',
|
||||
'amount_min',
|
||||
'foreign_amount_is',
|
||||
'foreign_amount',
|
||||
'foreign_amount_less',
|
||||
'foreign_amount_max',
|
||||
'foreign_amount_more',
|
||||
'foreign_amount_min',
|
||||
];
|
||||
if (in_array($array['type'], $amountFields, true) && '0' === $array['value']) {
|
||||
$array['value'] = '0.00';
|
||||
}
|
||||
return $array;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
@@ -90,7 +122,7 @@ class RuleFormRequest extends FormRequest
|
||||
$return[] = [
|
||||
'type' => $action['type'] ?? 'invalid',
|
||||
'value' => $action['value'] ?? '',
|
||||
'stop_processing' => 1 === (int) $stopProcessing,
|
||||
'stop_processing' => 1 === (int)$stopProcessing,
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -121,9 +153,9 @@ class RuleFormRequest extends FormRequest
|
||||
'stop_processing' => 'boolean',
|
||||
'rule_group_id' => 'required|belongsToUser:rule_groups',
|
||||
'trigger' => 'required|in:store-journal,update-journal',
|
||||
'triggers.*.type' => 'required|in:' . implode(',', $validTriggers),
|
||||
'triggers.*.type' => 'required|in:'.implode(',', $validTriggers),
|
||||
'triggers.*.value' => sprintf('required_if:triggers.*.type,%s|min:1|ruleTriggerValue', $contextTriggers),
|
||||
'actions.*.type' => 'required|in:' . implode(',', $validActions),
|
||||
'actions.*.type' => 'required|in:'.implode(',', $validActions),
|
||||
'actions.*.value' => sprintf('required_if:actions.*.type,%s|min:0|max:255|ruleActionValue', $contextActions),
|
||||
'strict' => 'in:0,1',
|
||||
];
|
||||
@@ -132,7 +164,7 @@ class RuleFormRequest extends FormRequest
|
||||
$rule = $this->route()->parameter('rule');
|
||||
|
||||
if (null !== $rule) {
|
||||
$rules['title'] = 'required|between:1,100|uniqueObjectForUser:rules,title,' . $rule->id;
|
||||
$rules['title'] = 'required|between:1,100|uniqueObjectForUser:rules,title,'.$rule->id;
|
||||
}
|
||||
|
||||
return $rules;
|
||||
|
@@ -26,6 +26,7 @@ use Carbon\Carbon;
|
||||
use Eloquent;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Database\Eloquent\Builder as EloquentBuilder;
|
||||
use Illuminate\Database\Eloquent\Casts\Attribute;
|
||||
use Illuminate\Database\Eloquent\Collection;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
@@ -290,4 +291,16 @@ class Account extends Model
|
||||
{
|
||||
return $this->belongsTo(User::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the virtual balance
|
||||
*
|
||||
* @return Attribute
|
||||
*/
|
||||
protected function virtualBalance(): Attribute
|
||||
{
|
||||
return Attribute::make(
|
||||
get: fn($value) => (string) $value,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@@ -25,6 +25,7 @@ declare(strict_types=1);
|
||||
namespace FireflyIII\Models;
|
||||
|
||||
use Eloquent;
|
||||
use Illuminate\Database\Eloquent\Casts\Attribute;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
@@ -88,4 +89,14 @@ class AutoBudget extends Model
|
||||
{
|
||||
return $this->belongsTo(TransactionCurrency::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Attribute
|
||||
*/
|
||||
protected function amount(): Attribute
|
||||
{
|
||||
return Attribute::make(
|
||||
get: fn($value) => (string) $value,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@@ -1,4 +1,5 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* AvailableBudget.php
|
||||
* Copyright (c) 2019 james@firefly-iii.org
|
||||
@@ -24,6 +25,7 @@ namespace FireflyIII\Models;
|
||||
|
||||
use Eloquent;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Database\Eloquent\Casts\Attribute;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
@@ -34,17 +36,17 @@ use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
||||
/**
|
||||
* FireflyIII\Models\AvailableBudget
|
||||
*
|
||||
* @property int $id
|
||||
* @property Carbon|null $created_at
|
||||
* @property Carbon|null $updated_at
|
||||
* @property Carbon|null $deleted_at
|
||||
* @property int $user_id
|
||||
* @property int $transaction_currency_id
|
||||
* @property string $amount
|
||||
* @property Carbon $start_date
|
||||
* @property Carbon $end_date
|
||||
* @property int $id
|
||||
* @property Carbon|null $created_at
|
||||
* @property Carbon|null $updated_at
|
||||
* @property Carbon|null $deleted_at
|
||||
* @property int $user_id
|
||||
* @property int $transaction_currency_id
|
||||
* @property string $amount
|
||||
* @property Carbon $start_date
|
||||
* @property Carbon $end_date
|
||||
* @property-read TransactionCurrency $transactionCurrency
|
||||
* @property-read User $user
|
||||
* @property-read User $user
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|AvailableBudget newModelQuery()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|AvailableBudget newQuery()
|
||||
* @method static Builder|AvailableBudget onlyTrashed()
|
||||
@@ -61,7 +63,7 @@ use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
||||
* @method static Builder|AvailableBudget withTrashed()
|
||||
* @method static Builder|AvailableBudget withoutTrashed()
|
||||
* @mixin Eloquent
|
||||
* @property int|null $user_group_id
|
||||
* @property int|null $user_group_id
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|AvailableBudget whereUserGroupId($value)
|
||||
*/
|
||||
class AvailableBudget extends Model
|
||||
@@ -88,7 +90,7 @@ class AvailableBudget extends Model
|
||||
/**
|
||||
* Route binder. Converts the key in the URL to the specified object (or throw 404).
|
||||
*
|
||||
* @param string $value
|
||||
* @param string $value
|
||||
*
|
||||
* @return AvailableBudget
|
||||
* @throws NotFoundHttpException
|
||||
@@ -96,7 +98,7 @@ class AvailableBudget extends Model
|
||||
public static function routeBinder(string $value): AvailableBudget
|
||||
{
|
||||
if (auth()->check()) {
|
||||
$availableBudgetId = (int) $value;
|
||||
$availableBudgetId = (int)$value;
|
||||
/** @var User $user */
|
||||
$user = auth()->user();
|
||||
/** @var AvailableBudget $availableBudget */
|
||||
@@ -125,4 +127,14 @@ class AvailableBudget extends Model
|
||||
{
|
||||
return $this->belongsTo(User::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Attribute
|
||||
*/
|
||||
protected function amount(): Attribute
|
||||
{
|
||||
return Attribute::make(
|
||||
get: fn ($value) => (string)$value,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@@ -25,6 +25,7 @@ namespace FireflyIII\Models;
|
||||
use Eloquent;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Database\Eloquent\Casts\Attribute;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
use Illuminate\Support\Carbon;
|
||||
@@ -99,4 +100,24 @@ class CurrencyExchangeRate extends Model
|
||||
{
|
||||
return $this->belongsTo(User::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Attribute
|
||||
*/
|
||||
protected function rate(): Attribute
|
||||
{
|
||||
return Attribute::make(
|
||||
get: fn($value) => (string) $value,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Attribute
|
||||
*/
|
||||
protected function userRate(): Attribute
|
||||
{
|
||||
return Attribute::make(
|
||||
get: fn($value) => (string) $value,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@@ -23,6 +23,7 @@ declare(strict_types=1);
|
||||
namespace FireflyIII\Models;
|
||||
|
||||
use Eloquent;
|
||||
use Illuminate\Database\Eloquent\Casts\Attribute;
|
||||
use Illuminate\Database\Eloquent\Collection;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
@@ -154,7 +155,7 @@ class PiggyBank extends Model
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all of the tags for the post.
|
||||
* Get all the tags for the post.
|
||||
*/
|
||||
public function objectGroups()
|
||||
{
|
||||
@@ -188,4 +189,16 @@ class PiggyBank extends Model
|
||||
{
|
||||
$this->attributes['targetamount'] = (string) $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the max amount
|
||||
*
|
||||
* @return Attribute
|
||||
*/
|
||||
protected function targetamount(): Attribute
|
||||
{
|
||||
return Attribute::make(
|
||||
get: fn($value) => (string) $value,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@@ -24,6 +24,7 @@ declare(strict_types=1);
|
||||
namespace FireflyIII\Models;
|
||||
|
||||
use Eloquent;
|
||||
use Illuminate\Database\Eloquent\Casts\Attribute;
|
||||
use Illuminate\Database\Eloquent\Collection;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
@@ -164,4 +165,24 @@ class RecurrenceTransaction extends Model
|
||||
{
|
||||
return $this->belongsTo(TransactionType::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Attribute
|
||||
*/
|
||||
protected function amount(): Attribute
|
||||
{
|
||||
return Attribute::make(
|
||||
get: fn($value) => (string) $value,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Attribute
|
||||
*/
|
||||
protected function foreignAmount(): Attribute
|
||||
{
|
||||
return Attribute::make(
|
||||
get: fn($value) => (string) $value,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@@ -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',
|
||||
],
|
||||
];
|
||||
|
||||
/**
|
||||
|
@@ -58,7 +58,7 @@ class RouteServiceProvider extends ServiceProvider
|
||||
->group(base_path('routes/api.php'));
|
||||
|
||||
Route::prefix('api/v1/cron')
|
||||
->middleware('apiY')
|
||||
->middleware('api_basic')
|
||||
->namespace($this->namespace)
|
||||
->group(base_path('routes/api-noauth.php'));
|
||||
|
||||
|
@@ -486,6 +486,13 @@ class AccountRepository implements AccountRepositoryInterface
|
||||
*/
|
||||
public function getAccountCurrency(Account $account): ?TransactionCurrency
|
||||
{
|
||||
$type = $account->accountType->type;
|
||||
$list = config('firefly.valid_currency_account_types');
|
||||
|
||||
// return null if not in this list.
|
||||
if(!in_array($type, $list, true)) {
|
||||
return null;
|
||||
}
|
||||
$currencyId = (int) $this->getMetaValue($account, 'currency_id');
|
||||
if ($currencyId > 0) {
|
||||
return TransactionCurrency::find($currencyId);
|
||||
|
@@ -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();
|
||||
|
@@ -24,6 +24,7 @@ declare(strict_types=1);
|
||||
namespace FireflyIII\Services\Internal\Destroy;
|
||||
|
||||
use Exception;
|
||||
use FireflyIII\Events\DestroyedTransactionGroup;
|
||||
use FireflyIII\Models\TransactionGroup;
|
||||
|
||||
/**
|
||||
@@ -49,6 +50,8 @@ class TransactionGroupDestroyService
|
||||
} catch (Exception $e) { // @phpstan-ignore-line
|
||||
// @ignoreException
|
||||
}
|
||||
// trigger just after destruction
|
||||
event(new DestroyedTransactionGroup($transactionGroup));
|
||||
}
|
||||
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user