Fix cron job and layout

This commit is contained in:
Sander Dorigo
2026-08-24 10:43:17 +02:00
parent 6257a26e19
commit b5f48e8652
9 changed files with 129 additions and 12 deletions
+18
View File
@@ -27,6 +27,7 @@ namespace FireflyIII\Console\Commands\Tools;
use Carbon\Carbon;
use FireflyIII\Console\Commands\ShowsFriendlyMessages;
use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Repositories\User\UserRepositoryInterface;
use FireflyIII\Support\Cronjobs\AutoBudgetCronjob;
use FireflyIII\Support\Cronjobs\BillWarningCronjob;
use FireflyIII\Support\Cronjobs\ExchangeRatesCronjob;
@@ -34,6 +35,7 @@ use FireflyIII\Support\Cronjobs\RecurringCronjob;
use FireflyIII\Support\Cronjobs\UpdateCheckCronjob;
use FireflyIII\Support\Cronjobs\WebhookCronjob;
use FireflyIII\Support\Facades\AppConfiguration;
use FireflyIII\User;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\Log;
use InvalidArgumentException;
@@ -55,8 +57,18 @@ class Cron extends Command
{--send-webhook-messages : Sends any stray webhook messages (with a maximum of 5).}
';
private User $admin;
public function handle(): int
{
/** @var UserRepositoryInterface $repository */
$repository = app(UserRepositoryInterface::class);
$admin = $repository->getUsersByRole('owner')?->first();
if(null === $admin) {
$this->friendlyError('There is no user in the system with the "owner"-role, cannot continue.');
return 1;
}
$this->admin = $admin;
$doAll
= !$this->option('download-cer')
&& !$this->option('create-recurring')
@@ -147,6 +159,7 @@ class Cron extends Command
{
$autoBudget = new AutoBudgetCronjob();
$autoBudget->setForce($force);
$autoBudget->setUser($this->admin);
// set date in cron job:
if ($date instanceof Carbon) {
$autoBudget->setDate($date);
@@ -169,6 +182,7 @@ class Cron extends Command
{
$updateCheck = new UpdateCheckCronjob();
$updateCheck->setForce($force);
$updateCheck->setUser($this->admin);
$updateCheck->fire();
if ($updateCheck->jobErrored) {
@@ -187,6 +201,7 @@ class Cron extends Command
Log::debug(sprintf('Created new ExchangeRateConverter in %s', __METHOD__));
$exchangeRates = new ExchangeRatesCronjob();
$exchangeRates->setForce($force);
$exchangeRates->setUser($this->admin);
// set date in cron job:
if ($date instanceof Carbon) {
$exchangeRates->setDate($date);
@@ -212,6 +227,7 @@ class Cron extends Command
{
$recurring = new RecurringCronjob();
$recurring->setForce($force);
$recurring->setUser($this->admin);
// set date in cron job:
if ($date instanceof Carbon) {
@@ -237,6 +253,7 @@ class Cron extends Command
{
$subscriptionWarningJob = new BillWarningCronjob();
$subscriptionWarningJob->setForce($force);
$subscriptionWarningJob->setUser($this->admin);
// set date in cron job:
if ($date instanceof Carbon) {
$subscriptionWarningJob->setDate($date);
@@ -259,6 +276,7 @@ class Cron extends Command
{
$webhook = new WebhookCronjob();
$webhook->setForce($force);
$webhook->setUser($this->admin);
// set date in cron job:
if ($date instanceof Carbon) {
$webhook->setDate($date);
+8
View File
@@ -417,4 +417,12 @@ class UserRepository implements UserRepositoryInterface
return null !== $invitee;
}
public function getUsersByRole(string $role): Collection
{
return User::leftJoin('role_user','role_user.user_id','=','users.id')
->leftJoin('roles','roles.id','role_user.role_id')
->where('roles.name', $role)
->get();
}
}
@@ -49,6 +49,8 @@ interface UserRepositoryInterface
*/
public function all(): Collection;
public function getUsersByRole(string $role): Collection;
/**
* Gives a user a role.
*/
+1 -1
View File
@@ -1,5 +1,5 @@
{
"name": "firefly-iii",
"name": "release",
"lockfileVersion": 3,
"requires": true,
"packages": {
@@ -0,0 +1,35 @@
/*
* get.js
* 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/>.
*/
import {api} from "../../../boot/axios";
export default class Get {
/**
*
* @param params
* @returns {Promise<AxiosResponse<any>>}
*/
list(params) {
return api.get('/api/v1/link-types', {params: params});
}
}
@@ -53,6 +53,7 @@ import {onMapZoom} from "./shared/on-map-zoom.js";
import {clearLocation} from './shared/clear-location.js';
import bootstrap from "bootstrap/dist/js/bootstrap.bundle.js";
import {removeSplit} from "./shared/remove-split.js";
import {loadTransactionLinks} from './shared/load-transaction-links.js';
let create = function () {
@@ -65,6 +66,7 @@ let create = function () {
// links are stored in "links" for each transaction journal.
links: [],
preparedLinks: [],
// maps are stored in this array so they can be referred to.
maps: [],
@@ -83,6 +85,7 @@ let create = function () {
formStates: {
loadingCurrencies: true,
loadingBudgets: true,
loadingLinks: true,
loadingPiggyBanks: true,
loadingSubscriptions: true,
isSubmitting: false,
@@ -260,6 +263,7 @@ let create = function () {
this.formData.foreignCurrencies = data.foreignCurrencies;
});
loadBudgets(false).then(data => {
this.formData.budgets = data;
this.formStates.loadingBudgets = false;
@@ -276,6 +280,14 @@ let create = function () {
// load custom field preference and enable/disable those fields.
this.loadCustomFields().then(data => {
this.formBehaviour.customFields = data;
// linked-transactions-search
if(true === data.links) {
loadTransactionLinks().then(data => {
//console.log(data);
this.formData.linkTypes = data;
this.formStates.loadingLinks = false;
});
}
});
@@ -0,0 +1,25 @@
import Get from "../../../api/model/link-type/get.js";
export function loadTransactionLinks() {
let params = {
page: 1, limit: 1337
};
let getter = new Get();
return getter.list(params).then((response) => {
let set = [];
for (let i in response.data.data) {
if (response.data.data.hasOwnProperty(i)) {
let current = response.data.data[i];
let entry = {
id: current.id,
name: current.attributes.name,
inward: current.attributes.inward,
outward: current.attributes.outward,
editable: current.attributes.editable,
};
set.push(entry);
}
}
return set;
});
}
@@ -138,11 +138,11 @@
</div>
<!-- Modal for links -->
<div class="modal modal-xl fade" :id="'linksModal_' + index" data-bs-backdrop="static" tabindex="-1"
aria-labelledby="exampleModalLabel" aria-hidden="true">
:aria-labelledby="'linksModal_' + index" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h1 class="modal-title fs-5" id="exampleModalLabel">Transaction relations</h1>
<h1 class="modal-title fs-5" :id="'linksModal_' + index">Transaction relations</h1>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
@@ -150,10 +150,10 @@
<div class="row">
<div class="col">
<p><em class="text-info">
Bla bla bla explanation.
TODO Bla bla bla explanation.
</em>
<template x-if="0 === links[index].length">
<em>This transaction has no relations to other transactions (yet).</em>
<em>TODO This transaction has no relations to other transactions (yet).</em>
</template>
</p>
</div>
@@ -177,19 +177,26 @@
</template>
<div class="row">
<div class="col">
<h5>Add a new relation</h5>
<h5>Link this (TODO NEW?) transaction to another transaction</h5>
<div class="row">
<div class="col">
<div class="col w-30">
<input type="text" readonly class="form-control-plaintext" value="This transaction">
</div>
<div class="col">
<input type="text" class="form-control" placeholder="First name" aria-label="First name">
<select class="form-control" name="link_type_id" :data-index="index" :id="'link_type_id_' + index">
<template x-for="type in formData.linkTypes ">
<option :value="type.id + '_inward'" :label="type.inward" x-text="type.inward"></option>
</template>
<template x-for="type in formData.linkTypes">
<option :value="type.id + '_outward'" :label="type.outward" x-text="type.outward"></option>
</template>
</select>
</div>
<div class="col">
<input type="text" class="form-control" placeholder="Last name" aria-label="Last name">
<input type="text" name="search" class="form-control linked-transactions-search" placeholder="TODO Search here..." aria-label="TODO Search here...">
</div>
<div class="col">
<input type="submit" class="btn btn-primary">
<div class="col w-15 text-end">
<input type="submit" name="submit" value="TODO Save" class="btn btn-primary">
</div>
</div>
</div>
@@ -7,7 +7,17 @@
<div class="form-group">
<div class="form-control-plaintext">
<button class="btn btn-sm btn-outline-primary" data-bs-toggle="modal" :data-bs-target="'#linksModal_' + index" type="button">Manage related transactions</button>
<template x-if="formStates.loadingLinks">
<button disabled="disabled" class="btn btn-sm btn-outline-primary" data-bs-toggle="modal" :data-bs-target="'#linksModal_' + index" type="button">
<div class="spinner-border spinner-border-sm" role="status">
<span class="visually-hidden">{{ __('firefly.thinking') }}</span>
</div>
</button>
</template>
<template x-if="!formStates.loadingLinks">
<button class="btn btn-sm btn-outline-primary" data-bs-toggle="modal" :data-bs-target="'#linksModal_' + index" type="button">
TODO Manage related transactions</button>
</template>
</div>
</div>
</div>