mirror of
https://github.com/firefly-iii/firefly-iii.git
synced 2025-09-03 11:25:18 +00:00
Compare commits
17 Commits
develop-20
...
develop-20
Author | SHA1 | Date | |
---|---|---|---|
|
30a417ea3c | ||
|
695ed940e0 | ||
|
1353554cf8 | ||
|
e1ba2732af | ||
|
42b57c0e0e | ||
|
a6072753b2 | ||
|
e92c224c39 | ||
|
a3ed7ec8f6 | ||
|
17a2f99dff | ||
|
c14971543c | ||
|
55f899608d | ||
|
83be63f27e | ||
|
ed48d190e5 | ||
|
3c3b6615e6 | ||
|
e71e5a877b | ||
|
b2a65dc660 | ||
|
d66dccd076 |
@@ -31,6 +31,7 @@ use FireflyIII\Exceptions\FireflyException;
|
|||||||
use FireflyIII\Models\Account;
|
use FireflyIII\Models\Account;
|
||||||
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
||||||
use FireflyIII\Support\Debug\Timer;
|
use FireflyIII\Support\Debug\Timer;
|
||||||
|
use FireflyIII\Support\Facades\Amount;
|
||||||
use FireflyIII\Support\Facades\Steam;
|
use FireflyIII\Support\Facades\Steam;
|
||||||
use FireflyIII\Support\Http\Api\AccountFilter;
|
use FireflyIII\Support\Http\Api\AccountFilter;
|
||||||
use FireflyIII\User;
|
use FireflyIII\User;
|
||||||
@@ -79,17 +80,19 @@ class AccountController extends Controller
|
|||||||
*/
|
*/
|
||||||
public function accounts(AutocompleteRequest $request): JsonResponse
|
public function accounts(AutocompleteRequest $request): JsonResponse
|
||||||
{
|
{
|
||||||
$data = $request->getData();
|
$data = $request->getData();
|
||||||
$types = $data['types'];
|
$types = $data['types'];
|
||||||
$query = $data['query'];
|
$query = $data['query'];
|
||||||
$date = $data['date'] ?? today(config('app.timezone'));
|
$date = $data['date'] ?? today(config('app.timezone'));
|
||||||
$return = [];
|
$return = [];
|
||||||
Timer::start(sprintf('AC accounts "%s"', $query));
|
Timer::start(sprintf('AC accounts "%s"', $query));
|
||||||
$result = $this->repository->searchAccount((string) $query, $types, $this->parameters->get('limit'));
|
$result = $this->repository->searchAccount((string) $query, $types, $this->parameters->get('limit'));
|
||||||
|
|
||||||
// set date to subday + end-of-day for account balance. so it is at $date 23:59:59
|
// set date to subday + end-of-day for account balance. so it is at $date 23:59:59
|
||||||
$date->endOfDay();
|
$date->endOfDay();
|
||||||
|
|
||||||
|
$allBalances = Steam::accountsBalancesOptimized($result, $date, $this->primaryCurrency, $this->convertToPrimary);
|
||||||
|
|
||||||
/** @var Account $account */
|
/** @var Account $account */
|
||||||
foreach ($result as $account) {
|
foreach ($result as $account) {
|
||||||
$nameWithBalance = $account->name;
|
$nameWithBalance = $account->name;
|
||||||
@@ -98,15 +101,11 @@ class AccountController extends Controller
|
|||||||
if (in_array($account->accountType->type, $this->balanceTypes, true)) {
|
if (in_array($account->accountType->type, $this->balanceTypes, true)) {
|
||||||
// this one is correct.
|
// this one is correct.
|
||||||
Log::debug(sprintf('accounts: Call finalAccountBalance with date/time "%s"', $date->toIso8601String()));
|
Log::debug(sprintf('accounts: Call finalAccountBalance with date/time "%s"', $date->toIso8601String()));
|
||||||
$balance = Steam::finalAccountBalance($account, $date);
|
$balance = $allBalances[$account->id] ?? [];
|
||||||
$key = $this->convertToPrimary && $currency->id !== $this->primaryCurrency->id ? 'pc_balance' : 'balance';
|
$key = $this->convertToPrimary && $currency->id !== $this->primaryCurrency->id ? 'pc_balance' : 'balance';
|
||||||
$useCurrency = $this->convertToPrimary && $currency->id !== $this->primaryCurrency->id ? $this->primaryCurrency : $currency;
|
$useCurrency = $this->convertToPrimary && $currency->id !== $this->primaryCurrency->id ? $this->primaryCurrency : $currency;
|
||||||
$amount = $balance[$key] ?? '0';
|
$amount = $balance[$key] ?? '0';
|
||||||
$nameWithBalance = sprintf(
|
$nameWithBalance = sprintf('%s (%s)', $account->name, Amount::formatAnything($useCurrency, $amount, false));
|
||||||
'%s (%s)',
|
|
||||||
$account->name,
|
|
||||||
app('amount')->formatAnything($useCurrency, $amount, false)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$return[] = [
|
$return[] = [
|
||||||
|
@@ -69,7 +69,7 @@ class BillEventHandler
|
|||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Log::debug(sprintf('Will warning about %d overdue subscription(s).', count($toBeWarned)));
|
Log::debug(sprintf('Will warn about %d overdue subscription(s).', count($toBeWarned)));
|
||||||
if (0 === count($toBeWarned)) {
|
if (0 === count($toBeWarned)) {
|
||||||
Log::debug('No overdue subscriptions to warn about.');
|
Log::debug('No overdue subscriptions to warn about.');
|
||||||
|
|
||||||
@@ -84,7 +84,7 @@ class BillEventHandler
|
|||||||
Log::warning('should hit this ONCE');
|
Log::warning('should hit this ONCE');
|
||||||
|
|
||||||
try {
|
try {
|
||||||
Notification::send($user, new SubscriptionsOverdueReminder($overdue));
|
Notification::send($user, new SubscriptionsOverdueReminder($toBeWarned));
|
||||||
} catch (Exception $e) {
|
} catch (Exception $e) {
|
||||||
$message = $e->getMessage();
|
$message = $e->getMessage();
|
||||||
if (str_contains($message, 'Bcc')) {
|
if (str_contains($message, 'Bcc')) {
|
||||||
|
@@ -77,8 +77,8 @@ class NetWorth implements NetWorthInterface
|
|||||||
Log::debug(sprintf('Now in byAccounts("%s", "%s")', $ids, $date->format('Y-m-d H:i:s')));
|
Log::debug(sprintf('Now in byAccounts("%s", "%s")', $ids, $date->format('Y-m-d H:i:s')));
|
||||||
$primary = Amount::getPrimaryCurrency();
|
$primary = Amount::getPrimaryCurrency();
|
||||||
$netWorth = [];
|
$netWorth = [];
|
||||||
Log::debug(sprintf('NetWorth: finalAccountsBalance("%s")', $date->format('Y-m-d H:i:s')));
|
Log::debug(sprintf('NetWorth: accountsBalancesOptimized("%s")', $date->format('Y-m-d H:i:s')));
|
||||||
$balances = Steam::finalAccountsBalance($accounts, $date);
|
$balances = Steam::accountsBalancesOptimized($accounts, $date, null, $convertToPrimary);
|
||||||
|
|
||||||
/** @var Account $account */
|
/** @var Account $account */
|
||||||
foreach ($accounts as $account) {
|
foreach ($accounts as $account) {
|
||||||
@@ -143,8 +143,8 @@ class NetWorth implements NetWorthInterface
|
|||||||
*/
|
*/
|
||||||
$accounts = $this->getAccounts();
|
$accounts = $this->getAccounts();
|
||||||
$return = [];
|
$return = [];
|
||||||
Log::debug(sprintf('SumNetWorth: finalAccountsBalance("%s")', $date->format('Y-m-d H:i:s')));
|
Log::debug(sprintf('SumNetWorth: accountsBalancesOptimized("%s")', $date->format('Y-m-d H:i:s')));
|
||||||
$balances = Steam::finalAccountsBalance($accounts, $date);
|
$balances = Steam::accountsBalancesOptimized($accounts, $date);
|
||||||
foreach ($accounts as $account) {
|
foreach ($accounts as $account) {
|
||||||
$currency = $this->accountRepository->getAccountCurrency($account);
|
$currency = $this->accountRepository->getAccountCurrency($account);
|
||||||
$balance = $balances[$account->id]['balance'] ?? '0';
|
$balance = $balances[$account->id]['balance'] ?? '0';
|
||||||
|
@@ -93,10 +93,10 @@ class IndexController extends Controller
|
|||||||
$start->subSecond();
|
$start->subSecond();
|
||||||
|
|
||||||
$ids = $accounts->pluck('id')->toArray();
|
$ids = $accounts->pluck('id')->toArray();
|
||||||
Log::debug(sprintf('inactive start: finalAccountsBalance("%s")', $start->format('Y-m-d H:i:s')));
|
Log::debug(sprintf('inactive start: accountsBalancesOptimized("%s")', $start->format('Y-m-d H:i:s')));
|
||||||
Log::debug(sprintf('inactive end: finalAccountsBalance("%s")', $end->format('Y-m-d H:i:s')));
|
Log::debug(sprintf('inactive end: accountsBalancesOptimized("%s")', $end->format('Y-m-d H:i:s')));
|
||||||
$startBalances = Steam::finalAccountsBalance($accounts, $start);
|
$startBalances = Steam::accountsBalancesOptimized($accounts, $start, $this->primaryCurrency, $this->convertToPrimary);
|
||||||
$endBalances = Steam::finalAccountsBalance($accounts, $end);
|
$endBalances = Steam::accountsBalancesOptimized($accounts, $end, $this->primaryCurrency, $this->convertToPrimary);
|
||||||
$activities = Steam::getLastActivities($ids);
|
$activities = Steam::getLastActivities($ids);
|
||||||
|
|
||||||
|
|
||||||
@@ -170,10 +170,10 @@ class IndexController extends Controller
|
|||||||
$start->subSecond();
|
$start->subSecond();
|
||||||
|
|
||||||
$ids = $accounts->pluck('id')->toArray();
|
$ids = $accounts->pluck('id')->toArray();
|
||||||
Log::debug(sprintf('index start: finalAccountsBalance("%s")', $start->format('Y-m-d H:i:s')));
|
Log::debug(sprintf('index start: accountsBalancesOptimized("%s")', $start->format('Y-m-d H:i:s')));
|
||||||
Log::debug(sprintf('index end: finalAccountsBalance("%s")', $end->format('Y-m-d H:i:s')));
|
Log::debug(sprintf('index end: accountsBalancesOptimized("%s")', $end->format('Y-m-d H:i:s')));
|
||||||
$startBalances = Steam::finalAccountsBalance($accounts, $start);
|
$startBalances = Steam::accountsBalancesOptimized($accounts, $start, $this->primaryCurrency, $this->convertToPrimary);
|
||||||
$endBalances = Steam::finalAccountsBalance($accounts, $end);
|
$endBalances = Steam::accountsBalancesOptimized($accounts, $end, $this->primaryCurrency, $this->convertToPrimary);
|
||||||
$activities = Steam::getLastActivities($ids);
|
$activities = Steam::getLastActivities($ids);
|
||||||
|
|
||||||
|
|
||||||
|
@@ -114,10 +114,10 @@ class AccountController extends Controller
|
|||||||
$accountNames = $this->extractNames($accounts);
|
$accountNames = $this->extractNames($accounts);
|
||||||
|
|
||||||
// grab all balances
|
// grab all balances
|
||||||
Log::debug(sprintf('expenseAccounts: finalAccountsBalance("%s")', $start->format('Y-m-d H:i:s')));
|
Log::debug(sprintf('expenseAccounts: accountsBalancesOptimized("%s")', $start->format('Y-m-d H:i:s')));
|
||||||
Log::debug(sprintf('expenseAccounts: finalAccountsBalance("%s")', $end->format('Y-m-d H:i:s')));
|
Log::debug(sprintf('expenseAccounts: accountsBalancesOptimized("%s")', $end->format('Y-m-d H:i:s')));
|
||||||
$startBalances = Steam::finalAccountsBalance($accounts, $start, $this->primaryCurrency, $this->convertToPrimary);
|
$startBalances = Steam::accountsBalancesOptimized($accounts, $start, $this->primaryCurrency, $this->convertToPrimary);
|
||||||
$endBalances = Steam::finalAccountsBalance($accounts, $end, $this->primaryCurrency, $this->convertToPrimary);
|
$endBalances = Steam::accountsBalancesOptimized($accounts, $end, $this->primaryCurrency, $this->convertToPrimary);
|
||||||
|
|
||||||
// loop the accounts, then check for balance and currency info.
|
// loop the accounts, then check for balance and currency info.
|
||||||
foreach ($accounts as $account) {
|
foreach ($accounts as $account) {
|
||||||
@@ -654,10 +654,10 @@ class AccountController extends Controller
|
|||||||
$accountNames = $this->extractNames($accounts);
|
$accountNames = $this->extractNames($accounts);
|
||||||
|
|
||||||
// grab all balances
|
// grab all balances
|
||||||
Log::debug(sprintf('revAccounts: finalAccountsBalance("%s")', $start->format('Y-m-d H:i:s')));
|
Log::debug(sprintf('revAccounts: accountsBalancesOptimized("%s")', $start->format('Y-m-d H:i:s')));
|
||||||
Log::debug(sprintf('revAccounts: finalAccountsBalance("%s")', $end->format('Y-m-d H:i:s')));
|
Log::debug(sprintf('revAccounts: accountsBalancesOptimized("%s")', $end->format('Y-m-d H:i:s')));
|
||||||
$startBalances = Steam::finalAccountsBalance($accounts, $start);
|
$startBalances = Steam::accountsBalancesOptimized($accounts, $start, $this->primaryCurrency, $this->convertToPrimary);
|
||||||
$endBalances = Steam::finalAccountsBalance($accounts, $end);
|
$endBalances = Steam::accountsBalancesOptimized($accounts, $end, $this->primaryCurrency, $this->convertToPrimary);
|
||||||
|
|
||||||
|
|
||||||
// loop the accounts, then check for balance and currency info.
|
// loop the accounts, then check for balance and currency info.
|
||||||
|
@@ -92,13 +92,12 @@ class SubscriptionsOverdueReminder extends Notification
|
|||||||
*/
|
*/
|
||||||
public function toSlack(User $notifiable): SlackMessage
|
public function toSlack(User $notifiable): SlackMessage
|
||||||
{
|
{
|
||||||
$bill = $this->bill;
|
$url = route('bills.index');
|
||||||
$url = route('bills.show', [$bill->id]);
|
|
||||||
|
|
||||||
return new SlackMessage()
|
return new SlackMessage()
|
||||||
->warning()
|
->warning()
|
||||||
->attachment(static function ($attachment) use ($bill, $url): void {
|
->attachment(static function ($attachment) use ($url): void {
|
||||||
$attachment->title((string)trans('firefly.visit_bill', ['name' => $bill->name]), $url);
|
$attachment->title((string)trans('firefly.visit_bills'), $url);
|
||||||
})
|
})
|
||||||
->content($this->getSubject())
|
->content($this->getSubject())
|
||||||
;
|
;
|
||||||
|
@@ -50,10 +50,10 @@ class AccountTasker implements AccountTaskerInterface, UserGroupInterface
|
|||||||
$yesterday = clone $start;
|
$yesterday = clone $start;
|
||||||
$yesterday->subDay()->endOfDay(); // exactly up until $start but NOT including.
|
$yesterday->subDay()->endOfDay(); // exactly up until $start but NOT including.
|
||||||
$end->endOfDay(); // needs to be end of day to be correct.
|
$end->endOfDay(); // needs to be end of day to be correct.
|
||||||
Log::debug(sprintf('getAccountReport: finalAccountsBalance("%s")', $yesterday->format('Y-m-d H:i:s')));
|
Log::debug(sprintf('getAccountReport: accountsBalancesOptimized("%s")', $yesterday->format('Y-m-d H:i:s')));
|
||||||
Log::debug(sprintf('getAccountReport: finalAccountsBalance("%s")', $end->format('Y-m-d H:i:s')));
|
Log::debug(sprintf('getAccountReport: accountsBalancesOptimized("%s")', $end->format('Y-m-d H:i:s')));
|
||||||
$startSet = Steam::finalAccountsBalance($accounts, $yesterday);
|
$startSet = Steam::accountsBalancesOptimized($accounts, $yesterday);
|
||||||
$endSet = Steam::finalAccountsBalance($accounts, $end);
|
$endSet = Steam::accountsBalancesOptimized($accounts, $end);
|
||||||
Log::debug('Start of accountreport');
|
Log::debug('Start of accountreport');
|
||||||
|
|
||||||
/** @var AccountRepositoryInterface $repository */
|
/** @var AccountRepositoryInterface $repository */
|
||||||
|
@@ -321,6 +321,7 @@ class Steam
|
|||||||
|
|
||||||
public function accountsBalancesOptimized(Collection $accounts, Carbon $date, ?TransactionCurrency $primary = null, ?bool $convertToPrimary = null): array
|
public function accountsBalancesOptimized(Collection $accounts, Carbon $date, ?TransactionCurrency $primary = null, ?bool $convertToPrimary = null): array
|
||||||
{
|
{
|
||||||
|
Log::debug(sprintf('accountsBalancesOptimized: Called with date/time "%s"', $date->toIso8601String()));
|
||||||
$result = [];
|
$result = [];
|
||||||
$convertToPrimary ??= Amount::convertToPrimary();
|
$convertToPrimary ??= Amount::convertToPrimary();
|
||||||
$primary ??= Amount::getPrimaryCurrency();
|
$primary ??= Amount::getPrimaryCurrency();
|
||||||
@@ -520,17 +521,6 @@ class Steam
|
|||||||
return $total;
|
return $total;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function finalAccountsBalance(Collection $accounts, Carbon $date): array
|
|
||||||
{
|
|
||||||
Log::debug(sprintf('finalAccountsBalance: Call finalAccountBalance with date/time "%s"', $date->toIso8601String()));
|
|
||||||
$balances = [];
|
|
||||||
foreach ($accounts as $account) {
|
|
||||||
$balances[$account->id] = $this->finalAccountBalance($account, $date);
|
|
||||||
}
|
|
||||||
|
|
||||||
return $balances;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @throws FireflyException
|
* @throws FireflyException
|
||||||
*/
|
*/
|
||||||
|
51
changelog.md
51
changelog.md
@@ -3,6 +3,57 @@
|
|||||||
All notable changes to this project will be documented in this file.
|
All notable changes to this project will be documented in this file.
|
||||||
This project adheres to [Semantic Versioning](http://semver.org/).
|
This project adheres to [Semantic Versioning](http://semver.org/).
|
||||||
|
|
||||||
|
## 6.3.0 - 2025-08-xx
|
||||||
|
|
||||||
|
> ⚠️ Firefly III v6.3.0 introduces a lot of API changes that deal with multi-currency support. Make sure your beloved apps are updated to support this.
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- [Issue 6836](https://github.com/firefly-iii/firefly-iii/issues/6836) (Send email about coming/past-due bills) reported by @elgatho
|
||||||
|
- [Issue 9640](https://github.com/firefly-iii/firefly-iii/issues/9640) (UI Improvements for Rules) reported by @siriuspal
|
||||||
|
- [Issue 9650](https://github.com/firefly-iii/firefly-iii/issues/9650) (Extra line in bills overview) reported by @poudenes
|
||||||
|
- Add Arabic as language, translations follow.
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- [Issue 10071](https://github.com/firefly-iii/firefly-iii/issues/10071) (Allow toggling password field to text) reported by @ragul-engg
|
||||||
|
- Renamed all instances of "default" and "native" currency to "primary" currency. This influences translations and API endpoints. The database is not changed because that's difficult to do reliably.
|
||||||
|
|
||||||
|
### Deprecated
|
||||||
|
|
||||||
|
- Any API-field called `default_*` or `native_*`. Use `primary_*` instead.
|
||||||
|
- All v2 endpoints.
|
||||||
|
|
||||||
|
### Removed
|
||||||
|
|
||||||
|
- Any API-field called `default_*` or `native_*`. Use `primary_*` instead.
|
||||||
|
- All v2 endpoints.
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- [Issue 10565](https://github.com/firefly-iii/firefly-iii/issues/10565) (Unable to delete reconciliation transaction) reported by @berta24
|
||||||
|
- [Issue 10600](https://github.com/firefly-iii/firefly-iii/issues/10600) (Show attachmen iccon when listing tranactions) reported by @JcMinarro
|
||||||
|
- [Discussion 10618](https://github.com/orgs/firefly-iii/discussions/10618) (Starting balance includes transactions that occur at 00:00 on the 1st of month) started by @jteez
|
||||||
|
- [Issue 10646](https://github.com/firefly-iii/firefly-iii/issues/10646) (Webhooks fire even if disabled) reported by @lvu
|
||||||
|
- [Issue 10656](https://github.com/firefly-iii/firefly-iii/issues/10656) (spent info "per day" shows the period total) reported by @frank-bg
|
||||||
|
- [Issue 10678](https://github.com/firefly-iii/firefly-iii/issues/10678) (Transactions from asset to liability account do not appear on category reports.) reported by @slackspace-io
|
||||||
|
- [Issue 10687](https://github.com/firefly-iii/firefly-iii/issues/10687) (Creating new Piggy Bank via API fails (Unexpected empty currency)) reported by @Madnex
|
||||||
|
- [Issue 10700](https://github.com/firefly-iii/firefly-iii/issues/10700) (Setting financial year date is inconsistent due to timezone calculations) reported by @AgeManning
|
||||||
|
- [Issue 10702](https://github.com/firefly-iii/firefly-iii/issues/10702) (Wrong order of months in category report) reported by @kapuett
|
||||||
|
- [Issue 10704](https://github.com/firefly-iii/firefly-iii/issues/10704) (Some triggers with rule automation seems to have an issue) reported by @Alienlog
|
||||||
|
- [Issue 10706](https://github.com/firefly-iii/firefly-iii/issues/10706) (Add KRW in Default Currency List) reported by @readingsnail
|
||||||
|
- [Issue 10708](https://github.com/firefly-iii/firefly-iii/issues/10708) (Incomplete display of a rule when a trigger negates "description caontains") reported by @dethegeek
|
||||||
|
- [Issue 10709](https://github.com/firefly-iii/firefly-iii/issues/10709) (has_any_external_id search parameter invalid) reported by @Alienlog
|
||||||
|
- Tag overview will no longer search for tags dated < 1970.
|
||||||
|
|
||||||
|
### API
|
||||||
|
|
||||||
|
- All remaining API v2 endpoints are deprecated and removed in favour of the API v1 endpoints.
|
||||||
|
- All API read endpoints now support multi-currency. Fields such as the balance and amount fields will also be available as `pc_*`-fields. Objects with currency information also come with new `primary_currency_*` fields.
|
||||||
|
- All API read endpoints are DB optimized and should be faster.
|
||||||
|
- All documentation should be in sync again.
|
||||||
|
- [More info in the docs](https://docs.firefly-iii.org/references/firefly-iii/api/).
|
||||||
|
|
||||||
## 6.2.21 - 2025-07-18
|
## 6.2.21 - 2025-07-18
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
40
composer.lock
generated
40
composer.lock
generated
@@ -11618,16 +11618,16 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "phpunit/phpunit",
|
"name": "phpunit/phpunit",
|
||||||
"version": "12.3.0",
|
"version": "12.3.1",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/sebastianbergmann/phpunit.git",
|
"url": "https://github.com/sebastianbergmann/phpunit.git",
|
||||||
"reference": "264da860d6fe0d00582355a6ecbbf7ae57b44895"
|
"reference": "5fd1b6e8ab560e0c62600591d438d22a8d978d68"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/264da860d6fe0d00582355a6ecbbf7ae57b44895",
|
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/5fd1b6e8ab560e0c62600591d438d22a8d978d68",
|
||||||
"reference": "264da860d6fe0d00582355a6ecbbf7ae57b44895",
|
"reference": "5fd1b6e8ab560e0c62600591d438d22a8d978d68",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
@@ -11637,7 +11637,7 @@
|
|||||||
"ext-mbstring": "*",
|
"ext-mbstring": "*",
|
||||||
"ext-xml": "*",
|
"ext-xml": "*",
|
||||||
"ext-xmlwriter": "*",
|
"ext-xmlwriter": "*",
|
||||||
"myclabs/deep-copy": "^1.13.3",
|
"myclabs/deep-copy": "^1.13.4",
|
||||||
"phar-io/manifest": "^2.0.4",
|
"phar-io/manifest": "^2.0.4",
|
||||||
"phar-io/version": "^3.2.1",
|
"phar-io/version": "^3.2.1",
|
||||||
"php": ">=8.3",
|
"php": ">=8.3",
|
||||||
@@ -11653,7 +11653,7 @@
|
|||||||
"sebastian/exporter": "^7.0.0",
|
"sebastian/exporter": "^7.0.0",
|
||||||
"sebastian/global-state": "^8.0.0",
|
"sebastian/global-state": "^8.0.0",
|
||||||
"sebastian/object-enumerator": "^7.0.0",
|
"sebastian/object-enumerator": "^7.0.0",
|
||||||
"sebastian/type": "^6.0.2",
|
"sebastian/type": "^6.0.3",
|
||||||
"sebastian/version": "^6.0.0",
|
"sebastian/version": "^6.0.0",
|
||||||
"staabm/side-effects-detector": "^1.0.5"
|
"staabm/side-effects-detector": "^1.0.5"
|
||||||
},
|
},
|
||||||
@@ -11695,7 +11695,7 @@
|
|||||||
"support": {
|
"support": {
|
||||||
"issues": "https://github.com/sebastianbergmann/phpunit/issues",
|
"issues": "https://github.com/sebastianbergmann/phpunit/issues",
|
||||||
"security": "https://github.com/sebastianbergmann/phpunit/security/policy",
|
"security": "https://github.com/sebastianbergmann/phpunit/security/policy",
|
||||||
"source": "https://github.com/sebastianbergmann/phpunit/tree/12.3.0"
|
"source": "https://github.com/sebastianbergmann/phpunit/tree/12.3.1"
|
||||||
},
|
},
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
@@ -11719,7 +11719,7 @@
|
|||||||
"type": "tidelift"
|
"type": "tidelift"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"time": "2025-08-01T05:14:47+00:00"
|
"time": "2025-08-09T07:12:41+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "rector/rector",
|
"name": "rector/rector",
|
||||||
@@ -12509,16 +12509,16 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "sebastian/type",
|
"name": "sebastian/type",
|
||||||
"version": "6.0.2",
|
"version": "6.0.3",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/sebastianbergmann/type.git",
|
"url": "https://github.com/sebastianbergmann/type.git",
|
||||||
"reference": "1d7cd6e514384c36d7a390347f57c385d4be6069"
|
"reference": "e549163b9760b8f71f191651d22acf32d56d6d4d"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/sebastianbergmann/type/zipball/1d7cd6e514384c36d7a390347f57c385d4be6069",
|
"url": "https://api.github.com/repos/sebastianbergmann/type/zipball/e549163b9760b8f71f191651d22acf32d56d6d4d",
|
||||||
"reference": "1d7cd6e514384c36d7a390347f57c385d4be6069",
|
"reference": "e549163b9760b8f71f191651d22acf32d56d6d4d",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
@@ -12554,15 +12554,27 @@
|
|||||||
"support": {
|
"support": {
|
||||||
"issues": "https://github.com/sebastianbergmann/type/issues",
|
"issues": "https://github.com/sebastianbergmann/type/issues",
|
||||||
"security": "https://github.com/sebastianbergmann/type/security/policy",
|
"security": "https://github.com/sebastianbergmann/type/security/policy",
|
||||||
"source": "https://github.com/sebastianbergmann/type/tree/6.0.2"
|
"source": "https://github.com/sebastianbergmann/type/tree/6.0.3"
|
||||||
},
|
},
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
"url": "https://github.com/sebastianbergmann",
|
"url": "https://github.com/sebastianbergmann",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://liberapay.com/sebastianbergmann",
|
||||||
|
"type": "liberapay"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://thanks.dev/u/gh/sebastianbergmann",
|
||||||
|
"type": "thanks_dev"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://tidelift.com/funding/github/packagist/sebastian/type",
|
||||||
|
"type": "tidelift"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"time": "2025-03-18T13:37:31+00:00"
|
"time": "2025-08-09T06:57:12+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "sebastian/version",
|
"name": "sebastian/version",
|
||||||
|
@@ -79,7 +79,7 @@ return [
|
|||||||
// see cer.php for exchange rates feature flag.
|
// see cer.php for exchange rates feature flag.
|
||||||
],
|
],
|
||||||
'version' => 'develop/2025-08-09',
|
'version' => 'develop/2025-08-09',
|
||||||
'build_time' => 1754721409,
|
'build_time' => 1754750540,
|
||||||
'api_version' => '2.1.0', // field is no longer used.
|
'api_version' => '2.1.0', // field is no longer used.
|
||||||
'db_version' => 26,
|
'db_version' => 26,
|
||||||
|
|
||||||
|
10
package-lock.json
generated
10
package-lock.json
generated
@@ -4326,9 +4326,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/browserslist": {
|
"node_modules/browserslist": {
|
||||||
"version": "4.25.1",
|
"version": "4.25.2",
|
||||||
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.25.1.tgz",
|
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.25.2.tgz",
|
||||||
"integrity": "sha512-KGj0KoOMXLpSNkkEI6Z6mShmQy0bc1I+T7K9N81k4WWMrfz+6fQ6es80B/YLAeRoKvjYE1YSHHOW1qe9xIVzHw==",
|
"integrity": "sha512-0si2SJK3ooGzIawRu61ZdPCO1IncZwS8IzuX73sPZsXW6EQ/w/DAfPyKI8l1ETTCr2MnvqWitmlCUxgdul45jA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
@@ -4346,8 +4346,8 @@
|
|||||||
],
|
],
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"caniuse-lite": "^1.0.30001726",
|
"caniuse-lite": "^1.0.30001733",
|
||||||
"electron-to-chromium": "^1.5.173",
|
"electron-to-chromium": "^1.5.199",
|
||||||
"node-releases": "^2.0.19",
|
"node-releases": "^2.0.19",
|
||||||
"update-browserslist-db": "^1.1.3"
|
"update-browserslist-db": "^1.1.3"
|
||||||
},
|
},
|
||||||
|
@@ -141,9 +141,11 @@ return [
|
|||||||
// subscription is overdue.
|
// subscription is overdue.
|
||||||
'subscriptions_overdue_subject_multi' => 'You have :count subscriptions that are overdue to be paid',
|
'subscriptions_overdue_subject_multi' => 'You have :count subscriptions that are overdue to be paid',
|
||||||
'subscriptions_overdue_subject_single' => 'You have a subscription that is overdue to be paid',
|
'subscriptions_overdue_subject_single' => 'You have a subscription that is overdue to be paid',
|
||||||
'subscriptions_overdue_warning_intro' => 'You have :count subscription(s) that are overdue to be paid. At the following date(s) a payment was expected, but it has not yet arrived.',
|
'subscriptions_overdue_warning_intro_single' => 'You have one subscription that is overdue to be paid. At the following date(s) a payment was expected, but it has not yet arrived.',
|
||||||
'subscriptions_overdue_please_action' => 'Perhaps you have simply not linked a transaction to these subscription(s). In that case, please do so. You will NOT get another warning about these overdue bill(s).',
|
'subscriptions_overdue_warning_intro_multi' => 'You have :count subscription(s) that are overdue to be paid. At the following date(s) a payment was expected, but it has not yet arrived.',
|
||||||
'subscriptions_overdue_outro' => 'If you believe this message is wrong, please contact the Firefly III developer.',
|
'subscriptions_overdue_please_action_single' => 'Perhaps you have simply not linked a transaction to this subscription. In that case, please do so. You will NOT get another warning about this overdue subscription. A new warning will be sent out for the NEXT due payment.',
|
||||||
|
'subscriptions_overdue_please_action_multi' => 'Perhaps you have simply not linked a transaction to these subscriptions. In that case, please do so. You will NOT get another warning about these overdue subscriptions. A new warning will be sent out for the NEXT due payments.',
|
||||||
|
'subscriptions_overdue_outro' => 'If you believe this message is wrong, please contact the Firefly III developer. Thank you for using Firefly III.',
|
||||||
// bill warning
|
// bill warning
|
||||||
'bill_warning_subject_end_date' => 'Your subscription ":name" is due to end in :diff days',
|
'bill_warning_subject_end_date' => 'Your subscription ":name" is due to end in :diff days',
|
||||||
'bill_warning_subject_now_end_date' => 'Your subscription ":name" is due to end TODAY',
|
'bill_warning_subject_now_end_date' => 'Your subscription ":name" is due to end TODAY',
|
||||||
|
@@ -1875,6 +1875,7 @@ return [
|
|||||||
'subscr_expected_x_times' => 'Expect to pay {{amount}} {{times}} times this period',
|
'subscr_expected_x_times' => 'Expect to pay {{amount}} {{times}} times this period',
|
||||||
'not_or_not_yet' => 'Not (yet)',
|
'not_or_not_yet' => 'Not (yet)',
|
||||||
'visit_bill' => 'Visit subscription ":name" at Firefly III',
|
'visit_bill' => 'Visit subscription ":name" at Firefly III',
|
||||||
|
'visit_bills' => 'Visit subscriptions at Firefly III',
|
||||||
'match_between_amounts' => 'Subscription matches transactions between :low and :high.',
|
'match_between_amounts' => 'Subscription matches transactions between :low and :high.',
|
||||||
'running_again_loss' => 'Previously linked transactions to this subscription may lose their connection, if they (no longer) match the rule(s).',
|
'running_again_loss' => 'Previously linked transactions to this subscription may lose their connection, if they (no longer) match the rule(s).',
|
||||||
'bill_related_rules' => 'Rules related to this subscription',
|
'bill_related_rules' => 'Rules related to this subscription',
|
||||||
|
@@ -1,6 +1,10 @@
|
|||||||
@component('mail::message')
|
@component('mail::message')
|
||||||
{{ trans('email.subscriptions_overdue_warning_intro', ['count' => $count]) }}
|
@if(1 === $count)
|
||||||
|
{{ trans('email.subscriptions_overdue_warning_intro_single') }}
|
||||||
|
@endif
|
||||||
|
@if(1 !== $count)
|
||||||
|
{{ trans('email.subscriptions_overdue_warning_intro_multi', ['count' => $count]) }}
|
||||||
|
@endif
|
||||||
@foreach($info as $row)
|
@foreach($info as $row)
|
||||||
- {{ $row['bill']->name }}:
|
- {{ $row['bill']->name }}:
|
||||||
@foreach($row['pay_dates'] as $date)
|
@foreach($row['pay_dates'] as $date)
|
||||||
@@ -8,10 +12,13 @@
|
|||||||
@endforeach
|
@endforeach
|
||||||
@endforeach
|
@endforeach
|
||||||
|
|
||||||
{{ trans('email.subscriptions_overdue_please_action') }}
|
@if(1 === $count)
|
||||||
|
{{ trans('email.subscriptions_overdue_please_action_single') }}
|
||||||
|
@endif
|
||||||
|
@if(1 !== $count)
|
||||||
|
{{ trans('email.subscriptions_overdue_please_action_multi', ['count' => $count]) }}
|
||||||
|
@endif
|
||||||
|
|
||||||
{{ trans('email.subscriptions_overdue_outro') }}
|
{{ trans('email.subscriptions_overdue_outro') }}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@endcomponent
|
@endcomponent
|
||||||
|
@@ -46,8 +46,12 @@
|
|||||||
{% endif %}
|
{% endif %}
|
||||||
</td>
|
</td>
|
||||||
<td style="text-align: right;" class="piggySaved">
|
<td style="text-align: right;" class="piggySaved">
|
||||||
<span title="Saved so far"
|
<span title="Saved so far" style="text-align:right;">
|
||||||
style="text-align:right;">{{ formatAmountBySymbol(piggy.current_amount,piggy.currency_symbol,piggy.currency_decimal_places) }}</span>
|
{{ formatAmountBySymbol(piggy.current_amount,piggy.currency_symbol,piggy.currency_decimal_places) }}
|
||||||
|
{% if convertToPrimary and piggy.currency_id != primaryCurrency.id and null != piggy.pc_current_amount %}
|
||||||
|
({{ formatAmountBySymbol(piggy.pc_current_amount,primaryCurrency.symbol,primaryCurrency.decimal_places) }})
|
||||||
|
{% endif %}
|
||||||
|
</span>
|
||||||
</td>
|
</td>
|
||||||
<td class="hidden-sm hidden-xs" style="text-align:right;width:40px;">
|
<td class="hidden-sm hidden-xs" style="text-align:right;width:40px;">
|
||||||
{% if piggy.current_amount > 0 %}
|
{% if piggy.current_amount > 0 %}
|
||||||
@@ -86,16 +90,25 @@
|
|||||||
<td class="hidden-sm hidden-xs" style="text-align:right;">
|
<td class="hidden-sm hidden-xs" style="text-align:right;">
|
||||||
{% if null != piggy.target_amount and 0 != piggy.target_amount %}
|
{% if null != piggy.target_amount and 0 != piggy.target_amount %}
|
||||||
<span title="{{ 'target_amount'|_ }}">{{ formatAmountBySymbol(piggy.target_amount,piggy.currency_symbol,piggy.currency_decimal_places) }}</span>
|
<span title="{{ 'target_amount'|_ }}">{{ formatAmountBySymbol(piggy.target_amount,piggy.currency_symbol,piggy.currency_decimal_places) }}</span>
|
||||||
|
{% if convertToPrimary and piggy.currency_id != primaryCurrency.id and null != piggy.pc_target_amount %}
|
||||||
|
(<span title="{{ 'target_amount'|_ }}">{{ formatAmountBySymbol(piggy.pc_target_amount,primaryCurrency.symbol, primaryCurrency.decimal_places) }}</span>)
|
||||||
|
{% endif %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</td>
|
</td>
|
||||||
<td class="hidden-sm hidden-xs" style="text-align:right;">
|
<td class="hidden-sm hidden-xs" style="text-align:right;">
|
||||||
{% if piggy.left_to_save > 0 %}
|
{% if piggy.left_to_save > 0 %}
|
||||||
<span title="{{ 'left_to_save'|_ }}">{{ formatAmountBySymbol(piggy.left_to_save,piggy.currency_symbol,piggy.currency_decimal_places) }}</span>
|
<span title="{{ 'left_to_save'|_ }}">{{ formatAmountBySymbol(piggy.left_to_save,piggy.currency_symbol,piggy.currency_decimal_places) }}</span>
|
||||||
|
{% if convertToPrimary and piggy.currency_id != primaryCurrency.id and null != piggy.pc_left_to_save %}
|
||||||
|
(<span title="{{ 'left_to_save'|_ }}">{{ formatAmountBySymbol(piggy.pc_left_to_save, primaryCurrency.symbol,primaryCurrency.decimal_places) }}</span>)
|
||||||
|
{% endif %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</td>
|
</td>
|
||||||
<td class="hidden-sm hidden-xs" style="text-align:right;">
|
<td class="hidden-sm hidden-xs" style="text-align:right;">
|
||||||
{% if piggy.target_date and piggy.save_per_month %}
|
{% if piggy.target_date and piggy.save_per_month %}
|
||||||
{{ formatAmountBySymbol(piggy.save_per_month, piggy.currency_symbol, piggy.currency_decimal_places) }}
|
{{ formatAmountBySymbol(piggy.save_per_month, piggy.currency_symbol, piggy.currency_decimal_places) }}
|
||||||
|
{% if convertToPrimary and piggy.currency_id != primaryCurrency.id and null != piggy.pc_save_per_month %}
|
||||||
|
({{ formatAmountBySymbol(piggy.pc_save_per_month, primaryCurrency.symbol, primaryCurrency.decimal_places) }})
|
||||||
|
{% endif %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
Reference in New Issue
Block a user