Skip to content

Commit

Permalink
Release 8.1 snapshot (#247)
Browse files Browse the repository at this point in the history
* WIP: order book snapshots.

* WIP: OrderbookSnapshot. WIP: Sanity cron job, Schedulers using now Coroutines.

* WIP: Sanity checks. SystemService uses now new SystemSanityCheck.

* WIP: Sanity checks.

* WIP: Sanity checks.
  • Loading branch information
kreinhard authored Jan 1, 2025
1 parent 77161d0 commit 619985f
Show file tree
Hide file tree
Showing 34 changed files with 1,117 additions and 510 deletions.
3 changes: 2 additions & 1 deletion ToDo.adoc
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
Aktuell:
- Scripting: Ergebnis Unresolved reference 'memo', 'todo'.: line 94 to 94 (add only activated plugins)
- JsonValidatorTest anpassen.
- Zeitberichte: kost2.nummer:4.* dauert sehr lang, auch für kurze Zeiträume.
- Healthcheck (daily) with mail notification on errors. Mit Registrierung von Services (jcr, orderbook snaphosts etc.)
- Groovy-scripts: remove or fix.
- AG-Grid: setColumnStates wird nicht in den UserPrefs gespeichert.
- Wicket: Auftragsbuch: org.apache.wicket.core.request.mapper.StalePageException: A request to page '[Page class = org.projectforge.web.fibu.AuftragEditPage, id = 9, render count = 3]' has been made with stale 'renderCount'. The page will be re-rendered.
Expand Down
7 changes: 3 additions & 4 deletions projectforge-application/src/main/resources/i18nKeys.json
Original file line number Diff line number Diff line change
Expand Up @@ -714,7 +714,7 @@
{"i18nKey":"currencyConverter.percentage.help","bundleName":"I18nResources","translation":"You can enter amounts as well as percent values (e. g. 10%).","translationDE":"Es können sowohl Beträge als auch Prozentzahlen (z. B. 10%) eingegeben werden.","usedInClasses":["org.projectforge.web.fibu.RechnungCostEditTablePanel"],"usedInFiles":[]},
{"i18nKey":"currencyFormat","bundleName":"I18nResources","translation":"{0,number,,##0.00}","translationDE":"{0,number,,##0.00}","usedInClasses":[],"usedInFiles":[]},
{"i18nKey":"datatable.no-records-found","bundleName":"I18nResources","translation":"No records found.","translationDE":"Keine Einträge gefunden.","usedInClasses":[],"usedInFiles":[]},
{"i18nKey":"date","bundleName":"I18nResources","translation":"date","translationDE":"Datum","usedInClasses":["org.projectforge.business.book.BookDO","org.projectforge.business.fibu.OrderExport","org.projectforge.business.fibu.datev.EmployeeSalaryExportDao","org.projectforge.business.fibu.kost.KostZuweisungExport","org.projectforge.business.fibu.orderbookstorage.OrderbookStorageDO","org.projectforge.business.fibu.orderbookstorage.OrderbookStorageService","org.projectforge.business.orga.ContractDO","org.projectforge.business.orga.ContractDao","org.projectforge.business.orga.PostausgangDO","org.projectforge.business.orga.PosteingangDO","org.projectforge.business.scripting.ScriptParameterType","org.projectforge.business.vacation.model.LeaveAccountEntryDO","org.projectforge.business.vacation.repository.LeaveAccountEntryDao","org.projectforge.carddav.CardDavServerDebugWriter","org.projectforge.framework.persistence.database.json.DatabaseWriter","org.projectforge.plugins.banking.BankAccountRecordPagesRest","org.projectforge.plugins.liquidityplanning.LiquidityForecastCashFlow","org.projectforge.rest.VacationAccountPageRest","org.projectforge.rest.hr.LeaveAccountEntryPagesRest","org.projectforge.rest.orga.ContractPagesRest","org.projectforge.rest.orga.VisitorbookPagesRest","org.projectforge.web.fibu.AccountingRecordEditForm","org.projectforge.web.fibu.DatevImportStoragePanel","org.projectforge.web.wicket.I18nParamMap","org.projectforge.web.wicket.WebConstants","org.projectforge.web.wicket.components.DateTimePanel"],"usedInFiles":["./plugins/org.projectforge.plugins.datatransfer/src/main/resources/mail/dataTransferMail.html","./projectforge-wicket/src/main/java/org/projectforge/web/wicket/components/DateTimePanel.html"]},
{"i18nKey":"date","bundleName":"I18nResources","translation":"date","translationDE":"Datum","usedInClasses":["org.projectforge.business.book.BookDO","org.projectforge.business.fibu.OrderExport","org.projectforge.business.fibu.datev.EmployeeSalaryExportDao","org.projectforge.business.fibu.kost.KostZuweisungExport","org.projectforge.business.fibu.orderbooksnapshots.OrderbookSnapshotDO","org.projectforge.business.fibu.orderbooksnapshots.OrderbookSnapshotsService","org.projectforge.business.orga.ContractDO","org.projectforge.business.orga.ContractDao","org.projectforge.business.orga.PostausgangDO","org.projectforge.business.orga.PosteingangDO","org.projectforge.business.scripting.ScriptParameterType","org.projectforge.business.vacation.model.LeaveAccountEntryDO","org.projectforge.business.vacation.repository.LeaveAccountEntryDao","org.projectforge.carddav.CardDavServerDebugWriter","org.projectforge.framework.persistence.database.json.DatabaseWriter","org.projectforge.plugins.banking.BankAccountRecordPagesRest","org.projectforge.plugins.liquidityplanning.LiquidityForecastCashFlow","org.projectforge.rest.VacationAccountPageRest","org.projectforge.rest.hr.LeaveAccountEntryPagesRest","org.projectforge.rest.orga.ContractPagesRest","org.projectforge.rest.orga.VisitorbookPagesRest","org.projectforge.web.fibu.AccountingRecordEditForm","org.projectforge.web.fibu.DatevImportStoragePanel","org.projectforge.web.wicket.I18nParamMap","org.projectforge.web.wicket.WebConstants","org.projectforge.web.wicket.components.DateTimePanel"],"usedInFiles":["./plugins/org.projectforge.plugins.datatransfer/src/main/resources/mail/dataTransferMail.html","./projectforge-wicket/src/main/java/org/projectforge/web/wicket/components/DateTimePanel.html"]},
{"i18nKey":"date.begin","bundleName":"I18nResources","translation":"Start date","translationDE":"Beginndatum","usedInClasses":["org.projectforge.rest.core.AbstractPagesRest","org.projectforge.rest.scripting.AbstractScriptExecutePageRest"],"usedInFiles":[]},
{"i18nKey":"date.end","bundleName":"I18nResources","translation":"End date","translationDE":"Endedatum","usedInClasses":["org.projectforge.rest.core.AbstractPagesRest","org.projectforge.rest.scripting.AbstractScriptExecutePageRest"],"usedInFiles":[]},
{"i18nKey":"date.from","bundleName":"I18nResources","translation":"from","translationDE":"von","usedInClasses":[],"usedInFiles":[]},
Expand Down Expand Up @@ -2210,8 +2210,8 @@
{"i18nKey":"system.admin.alertMessage.copyAndPaste.title","bundleName":"I18nResources","translation":"For copy & paste","translationDE":"For copy & paste","usedInClasses":["org.projectforge.web.admin.AdminForm"],"usedInFiles":[]},
{"i18nKey":"system.admin.button.checkI18nProperties","bundleName":"I18nResources","translation":"Check i18n properties","translationDE":"Check i18n properties","usedInClasses":["org.projectforge.web.admin.AdminPage"],"usedInFiles":[]},
{"i18nKey":"system.admin.button.checkI18nProperties.tooltip","bundleName":"I18nResources","translation":"Check i18n properties for detecting missing translations in different languages.","translationDE":"Check i18n properties for detecting missing translations in different languages.","usedInClasses":["org.projectforge.web.admin.AdminPage"],"usedInFiles":[]},
{"i18nKey":"system.admin.button.checkJCRSanity","bundleName":"I18nResources","translation":"JCR sanity check","translationDE":"JCR sanity check","usedInClasses":["org.projectforge.web.admin.AdminPage"],"usedInFiles":[]},
{"i18nKey":"system.admin.button.checkJCRSanity.tooltip","bundleName":"I18nResources","translation":"Checks the whole document repository (JCR) by comparing check sums and file sizes.","translationDE":"Checks the whole document repository (JCR) by comparing check sums and file sizes.","usedInClasses":["org.projectforge.web.admin.AdminPage"],"usedInFiles":[]},
{"i18nKey":"system.admin.button.checkJCRSanity","bundleName":"I18nResources","translation":"JCR sanity check","translationDE":"JCR sanity check","usedInClasses":[],"usedInFiles":[]},
{"i18nKey":"system.admin.button.checkJCRSanity.tooltip","bundleName":"I18nResources","translation":"Checks the whole document repository (JCR) by comparing check sums and file sizes.","translationDE":"Checks the whole document repository (JCR) by comparing check sums and file sizes.","usedInClasses":[],"usedInFiles":[]},
{"i18nKey":"system.admin.button.checkSystemIntegrity","bundleName":"I18nResources","translation":"Check system integrity","translationDE":"Check system integrity","usedInClasses":["org.projectforge.web.admin.AdminPage"],"usedInFiles":[]},
{"i18nKey":"system.admin.button.checkSystemIntegrity.tooltip","bundleName":"I18nResources","translation":"Some basic checks are done (are there orphaned structure elements in the system?).","translationDE":"Some basic checks are done (are there orphaned structure elements in the system?).","usedInClasses":["org.projectforge.web.admin.AdminPage"],"usedInFiles":[]},
{"i18nKey":"system.admin.button.clearAlertMessage","bundleName":"I18nResources","translation":"Clear alert message","translationDE":"Clear alert message","usedInClasses":[],"usedInFiles":[]},
Expand Down Expand Up @@ -2247,7 +2247,6 @@
{"i18nKey":"system.admin.group.title.misc.logEntries","bundleName":"I18nResources","translation":"Format log entries","translationDE":"Format log entries","usedInClasses":["org.projectforge.web.admin.AdminForm"],"usedInFiles":[]},
{"i18nKey":"system.admin.group.title.systemChecksAndFunctionality.caches","bundleName":"I18nResources","translation":"Caches","translationDE":"Caches","usedInClasses":["org.projectforge.web.admin.AdminPage"],"usedInFiles":[]},
{"i18nKey":"system.admin.group.title.systemChecksAndFunctionality.configuration","bundleName":"I18nResources","translation":"Configuration","translationDE":"Configuration","usedInClasses":["org.projectforge.web.admin.AdminPage"],"usedInFiles":[]},
{"i18nKey":"system.admin.group.title.systemChecksAndFunctionality.miscChecks","bundleName":"I18nResources","translation":"Misc checks","translationDE":"Misc checks","usedInClasses":["org.projectforge.web.admin.AdminPage"],"usedInFiles":[]},
{"i18nKey":"system.admin.logViewer.autoRefresh","bundleName":"I18nResources","translation":"Auto refresh","translationDE":"Auto-Aktualisierung","usedInClasses":["org.projectforge.rest.admin.LogViewFilter"],"usedInFiles":[]},
{"i18nKey":"system.admin.logViewer.level","bundleName":"I18nResources","translation":"Loglevel","translationDE":"Log-Level","usedInClasses":["org.projectforge.common.logging.LoggingEventData","org.projectforge.rest.admin.LogViewFilter","org.projectforge.rest.admin.LogViewerEvent"],"usedInFiles":[]},
{"i18nKey":"system.admin.logViewer.loggerName","bundleName":"I18nResources","translation":"Logger name","translationDE":"Quelle","usedInClasses":["org.projectforge.common.logging.LoggingEventData"],"usedInFiles":[]},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ public class CronReindexingHourlyJob {
//@Scheduled(cron = "${projectforge.cron.hourly}")

/**
* TODO: If reindexing of database entries, modified in the last hour, this job should be reactivated.
* In ms.
*/
//@Scheduled(fixedDelay = 3600 * 1000, initialDelay = 120 * 1000)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@
import org.projectforge.business.fibu.KontoCache;
import org.projectforge.business.fibu.RechnungCache;
import org.projectforge.business.fibu.kost.KostCache;
import org.projectforge.business.jsonRest.RestCallService;
import org.projectforge.business.task.TaskDO;
import org.projectforge.business.jobs.CronSanityCheckJob;
import org.projectforge.jobs.JobListExecutionContext;
import org.projectforge.business.task.TaskDao;
import org.projectforge.business.task.TaskTree;
import org.projectforge.business.user.UserGroupCache;
Expand All @@ -40,9 +40,6 @@

import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
* Provides some system routines.
Expand All @@ -51,130 +48,80 @@
*/
@Service
public class SystemService {
private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(SystemService.class);
private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(SystemService.class);

@Autowired
private UserGroupCache userGroupCache;
@Autowired
private UserGroupCache userGroupCache;

@Autowired
private TaskDao taskDao;
@Autowired
private TaskDao taskDao;

@Autowired
private TaskTree taskTree;
@Autowired
private TaskTree taskTree;

@Autowired
private SystemInfoCache systemInfoCache;
@Autowired
private SystemInfoCache systemInfoCache;

@Autowired
private AuftragsCache auftragsCache;
@Autowired
private AuftragsCache auftragsCache;

@Autowired
private RechnungCache rechnungCache;
@Autowired
private CronSanityCheckJob cronSanityCheckJob;

@Autowired
private KontoCache kontoCache;
@Autowired
private RechnungCache rechnungCache;

@Autowired
private KostCache kostCache;
@Autowired
private KontoCache kontoCache;

@Autowired
private RestCallService restCallService;
@Autowired
private KostCache kostCache;

public String exportSchema() {
final SchemaExport exp = new SchemaExport();
File file;
try {
file = File.createTempFile("projectforge-schema", ".sql");
} catch (final IOException ex) {
log.error(ex.getMessage(), ex);
return ex.getMessage();
}
exp.exportSchema(file.getPath());
String result;
try {
result = FileUtils.readFileToString(file, "UTF-8");
} catch (final IOException ex) {
log.error(ex.getMessage(), ex);
return ex.getMessage();
}
file.delete();
return result;
}

/**
* Search for abandoned tasks (task outside the task hierarchy, unaccessible and unavailable for the users).
*
* @return
*/
public String checkSystemIntegrity() {
final StringBuilder buf = new StringBuilder();
buf.append("ProjectForge system integrity check.\n\n");
buf.append("------------------------------------\n");
buf.append("| |\n");
buf.append("| Task integrity (abandoned tasks) |\n");
buf.append("| |\n");
buf.append("------------------------------------\n");
final List<TaskDO> tasks = taskDao.selectAll(false);
buf.append("Found " + tasks.size() + " tasks.\n");
final Map<Long, TaskDO> taskMap = new HashMap<>();
for (final TaskDO task : tasks) {
taskMap.put(task.getId(), task);
}
boolean rootTask = false;
boolean abandonedTasks = false;
for (final TaskDO task : tasks) {
if (task.getParentTask() == null) {
if (rootTask) {
buf.append("\n*** Error: Found another root task:\n " + task + "\n");
} else {
buf.append("\nFound root task:\n " + task + "\n");
rootTask = true;
}
} else {
TaskDO ancestor = taskMap.get(task.getParentTaskId());
boolean rootTaskFound = false;
for (int i = 0; i < 50; i++) { // Max. depth of 50, otherwise cyclic task!
if (ancestor == null) {
break;
}
if (ancestor.getParentTaskId() == null) {
// Root task found, OK.
rootTaskFound = true;
break;
}
ancestor = taskMap.get(ancestor.getParentTaskId());
public String exportSchema() {
final SchemaExport exp = new SchemaExport();
File file;
try {
file = File.createTempFile("projectforge-schema", ".sql");
} catch (final IOException ex) {
log.error(ex.getMessage(), ex);
return ex.getMessage();
}
if (!rootTaskFound) {
buf.append("\n*** Error: Found abandoned task (cyclic tasks without path to root):\n " + task + "\n");
abandonedTasks = true;
} else {
buf.append('.');
exp.exportSchema(file.getPath());
String result;
try {
result = FileUtils.readFileToString(file, "UTF-8");
} catch (final IOException ex) {
log.error(ex.getMessage(), ex);
return ex.getMessage();
}
}
taskMap.put(task.getId(), task);
file.delete();
return result;
}
if (!abandonedTasks) {
buf.append("\n\nTest OK, no abandoned tasks detected.");
} else {
buf.append("\n\n*** Test FAILED, abandoned tasks detected.");

/**
* Search for abandoned tasks (task outside the task hierarchy, unaccessible and unavailable for the users).
*
* @return
*/
public String checkSystemIntegrity() {
JobListExecutionContext context = cronSanityCheckJob.execute();
return context.getReportAsText();
}

/**
* Refreshes the caches: TaskTree, userGroupCache and kost2.
*
* @return the name of the refreshed caches.
*/
public String refreshCaches() {
userGroupCache.forceReload();
taskTree.forceReload();
kontoCache.forceReload();
kostCache.forceReload();
rechnungCache.forceReload();
auftragsCache.forceReload();
systemInfoCache.forceReload();
BirthdayCache.getInstance().forceReload();
return "UserGroupCache, TaskTree, KontoCache, KostCache, RechnungCache, AuftragsCache, SystemInfoCache, BirthdayCache";
}
return buf.toString();
}

/**
* Refreshes the caches: TaskTree, userGroupCache and kost2.
*
* @return the name of the refreshed caches.
*/
public String refreshCaches() {
userGroupCache.forceReload();
taskTree.forceReload();
kontoCache.forceReload();
kostCache.forceReload();
rechnungCache.forceReload();
auftragsCache.forceReload();
systemInfoCache.forceReload();
BirthdayCache.getInstance().forceReload();
return "UserGroupCache, TaskTree, KontoCache, KostCache, RechnungCache, AuftragsCache, SystemInfoCache, BirthdayCache";
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
//
/////////////////////////////////////////////////////////////////////////////

package org.projectforge.business.fibu.orderbookstorage
package org.projectforge.business.fibu.orderbooksnapshots

import org.projectforge.business.fibu.AuftragDO
import org.projectforge.business.fibu.AuftragsStatus
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
//
/////////////////////////////////////////////////////////////////////////////

package org.projectforge.business.fibu.orderbookstorage
package org.projectforge.business.fibu.orderbooksnapshots

import mu.KotlinLogging
import org.projectforge.business.PfCaches
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
//
/////////////////////////////////////////////////////////////////////////////

package org.projectforge.business.fibu.orderbookstorage
package org.projectforge.business.fibu.orderbooksnapshots

import org.projectforge.business.fibu.*
import java.math.BigDecimal
Expand Down
Loading

0 comments on commit 619985f

Please sign in to comment.