From bb8877364114b82d84d8cedfb2cea87e72425903 Mon Sep 17 00:00:00 2001 From: Andrey Potapov Date: Thu, 24 Mar 2022 23:37:03 +0300 Subject: [PATCH 01/30] #2362 changing excel sheet name from default Sheet0 to name of file --- .../ru/runa/wfe/office/storage/JdbcStoreService.java | 2 +- .../java/ru/runa/wfe/office/storage/StoreService.java | 2 +- .../ru/runa/wfe/office/storage/StoreServiceImpl.java | 10 +++++++--- 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/wfe-office/src/main/java/ru/runa/wfe/office/storage/JdbcStoreService.java b/wfe-office/src/main/java/ru/runa/wfe/office/storage/JdbcStoreService.java index 3faa561747..45e916c927 100644 --- a/wfe-office/src/main/java/ru/runa/wfe/office/storage/JdbcStoreService.java +++ b/wfe-office/src/main/java/ru/runa/wfe/office/storage/JdbcStoreService.java @@ -67,7 +67,7 @@ public JdbcStoreService(VariableProvider variableProvider) { } @Override - public void createFileIfNotExist(String path) throws Exception { + public void createFileIfNotExist(String path, String tableName) throws Exception { // Do nothing } diff --git a/wfe-office/src/main/java/ru/runa/wfe/office/storage/StoreService.java b/wfe-office/src/main/java/ru/runa/wfe/office/storage/StoreService.java index b27d1e162d..0a271b18dd 100644 --- a/wfe-office/src/main/java/ru/runa/wfe/office/storage/StoreService.java +++ b/wfe-office/src/main/java/ru/runa/wfe/office/storage/StoreService.java @@ -17,7 +17,7 @@ public interface StoreService { String PROP_PATH = "path"; String PROP_FORMAT = "format"; - void createFileIfNotExist(String path) throws Exception; + void createFileIfNotExist(String path, String tableName) throws Exception; ExecutionResult findByFilter(Properties properties, UserType userType, String condition) throws Exception; diff --git a/wfe-office/src/main/java/ru/runa/wfe/office/storage/StoreServiceImpl.java b/wfe-office/src/main/java/ru/runa/wfe/office/storage/StoreServiceImpl.java index 252c417a9d..839ce273d1 100644 --- a/wfe-office/src/main/java/ru/runa/wfe/office/storage/StoreServiceImpl.java +++ b/wfe-office/src/main/java/ru/runa/wfe/office/storage/StoreServiceImpl.java @@ -66,7 +66,7 @@ public StoreServiceImpl(VariableProvider variableProvider) { } @Override - public void createFileIfNotExist(String path) throws InternalApplicationException { + public void createFileIfNotExist(String path, String tableName) throws InternalApplicationException { final File f = new File(path); if (f.exists() && f.isFile()) { return; @@ -83,7 +83,11 @@ public void createFileIfNotExist(String path) throws InternalApplicationExceptio } try (Workbook workbook = path.endsWith(XLSX_SUFFIX) ? new XSSFWorkbook() : new HSSFWorkbook(); OutputStream os = new FileOutputStream(path)) { - workbook.createSheet(); + if (tableName == null) { + workbook.createSheet(); + } else { + workbook.createSheet(tableName); + } workbook.write(os); } catch (Exception e) { log.error("", e); @@ -176,7 +180,7 @@ private void initParams(Properties properties) throws InternalApplicationExcepti final ExcelDataSource eds = (ExcelDataSource) dataSource; fullPath = eds.getFilePath() + "/" + tableName() + XLSX_SUFFIX; } - createFileIfNotExist(fullPath); + createFileIfNotExist(fullPath, tableName()); } @SuppressWarnings("unchecked") From 332721beec8d625f59efd3b05cc7aa01bdf9d9f2 Mon Sep 17 00:00:00 2001 From: Dofs Date: Wed, 18 May 2022 14:28:06 +0300 Subject: [PATCH 02/30] rm2644: TaskClassPresentation swimlane sorting is enabled --- .../ru/runa/wfe/task/TaskClassPresentation.java | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/wfe-core/src/main/java/ru/runa/wfe/task/TaskClassPresentation.java b/wfe-core/src/main/java/ru/runa/wfe/task/TaskClassPresentation.java index d02f63d06d..4bff6f63f7 100644 --- a/wfe-core/src/main/java/ru/runa/wfe/task/TaskClassPresentation.java +++ b/wfe-core/src/main/java/ru/runa/wfe/task/TaskClassPresentation.java @@ -21,6 +21,7 @@ package ru.runa.wfe.task; import java.util.Date; +import ru.runa.wfe.execution.Swimlane; import ru.runa.wfe.presentation.BatchPresentationConsts; import ru.runa.wfe.presentation.ClassPresentation; import ru.runa.wfe.presentation.DefaultDbSource; @@ -50,6 +51,18 @@ public class TaskClassPresentation extends ClassPresentation { private static final ClassPresentation INSTANCE = new TaskClassPresentation(); + private static class SwimlaneDbSource extends DefaultDbSource { + + public SwimlaneDbSource() { + super(Swimlane.class, "name"); + } + + @Override + public String getJoinExpression(String alias) { + return "instance.swimlane.id = " + alias + ".id"; + } + } + private TaskClassPresentation() { super(Task.class, "", false, new FieldDescriptor[] { // display name field type DB source isSort filter mode @@ -68,7 +81,7 @@ private TaskClassPresentation() { FieldFilterMode.NONE, "ru.runa.wf.web.html.TaskRootProcessIdTdBuilder", new Object[] {}), new FieldDescriptor(OWNER, String.class.getName(), new DefaultDbSource(Task.class, "executor.name"), true, FieldFilterMode.DATABASE, "ru.runa.wf.web.html.TaskOwnerTdBuilder", new Object[] {}), - new FieldDescriptor(TASK_SWIMLINE, String.class.getName(), new DefaultDbSource(Task.class, "swimlane.name"), false, + new FieldDescriptor(TASK_SWIMLINE, String.class.getName(), new SwimlaneDbSource(), true, FieldFilterMode.DATABASE, "ru.runa.wf.web.html.TaskRoleTdBuilder", new Object[] {}), new FieldDescriptor(TASK_VARIABLE, Variable.class.getName(), VariableDbSources.get("process"), true, FieldFilterMode.DATABASE, "ru.runa.wf.web.html.TaskVariableTdBuilder", new Object[] {}).setVariablePrototype(true), From aa337a6fb7b242291af986e98debb0b22ba50f5e Mon Sep 17 00:00:00 2001 From: Dofs Date: Thu, 16 Jun 2022 13:47:15 +0300 Subject: [PATCH 03/30] TNMS-659 do not ignore FAILED tokens in message and job execution --- .../impl/AddTokenMessageSelectorPatch.java | 2 +- .../ru/runa/wfe/execution/dao/TokenDao.java | 19 +++++++++++-------- .../wfe/execution/logic/ExecutionLogic.java | 4 ++-- .../main/java/ru/runa/wfe/job/dao/JobDao.java | 4 ++-- .../ru/runa/wfe/lang/bpmn2/TimerNode.java | 13 ++++--------- .../java/ru/runa/wfe/task/dao/TaskDao.java | 3 ++- .../wfe/service/impl/ReceiveMessageBean.java | 2 +- 7 files changed, 23 insertions(+), 24 deletions(-) diff --git a/wfe-core/src/main/java/ru/runa/wfe/commons/dbmigration/impl/AddTokenMessageSelectorPatch.java b/wfe-core/src/main/java/ru/runa/wfe/commons/dbmigration/impl/AddTokenMessageSelectorPatch.java index 25e8d65e5d..85415a8d36 100644 --- a/wfe-core/src/main/java/ru/runa/wfe/commons/dbmigration/impl/AddTokenMessageSelectorPatch.java +++ b/wfe-core/src/main/java/ru/runa/wfe/commons/dbmigration/impl/AddTokenMessageSelectorPatch.java @@ -28,7 +28,7 @@ protected void executeDDLBefore() { @Override public void postExecute() { - List tokens = tokenDao.findByMessageSelectorIsNullAndExecutionStatusIsActive(); + List tokens = tokenDao.findByMessageSelectorIsNullAndExecutionStatusIsNotEnded(); log.info("Updating " + tokens.size() + " tokens message selector"); for (Token token : tokens) { ProcessDefinition processDefinition = processDefinitionLoader.getDefinition(token.getProcess()); diff --git a/wfe-core/src/main/java/ru/runa/wfe/execution/dao/TokenDao.java b/wfe-core/src/main/java/ru/runa/wfe/execution/dao/TokenDao.java index e705462a6c..cd6d0c98cd 100644 --- a/wfe-core/src/main/java/ru/runa/wfe/execution/dao/TokenDao.java +++ b/wfe-core/src/main/java/ru/runa/wfe/execution/dao/TokenDao.java @@ -19,9 +19,10 @@ @Component public class TokenDao extends GenericDao { - public List findByNodeTypeAndExecutionStatusIsActive(NodeType nodeType) { + public List findByNodeTypeInActiveProcesses(NodeType nodeType) { QToken t = QToken.token; - return queryFactory.selectFrom(t).where(t.nodeType.eq(nodeType).and(t.executionStatus.eq(ExecutionStatus.ACTIVE))).fetch(); + return queryFactory.selectFrom(t).where(t.nodeType.eq(nodeType).and(t.executionStatus.ne(ExecutionStatus.SUSPENDED)).and(t.endDate.isNull())) + .fetch(); } public List findByProcessAndExecutionStatusIsNotEnded(ru.runa.wfe.execution.Process process) { @@ -52,21 +53,23 @@ public List findByProcessAndNodeIdAndExecutionStatusIsEndedAndAbleToReact } - public List findByMessageSelectorIsNullAndExecutionStatusIsActive() { + public List findByMessageSelectorIsNullAndExecutionStatusIsNotEnded() { QToken t = QToken.token; return queryFactory.selectFrom(t) - .where(t.nodeType.eq(NodeType.RECEIVE_MESSAGE).and(t.messageSelector.isNull()).and(t.executionStatus.eq(ExecutionStatus.ACTIVE))) +.where(t.nodeType.eq(NodeType.RECEIVE_MESSAGE).and(t.messageSelector.isNull()).and(t.endDate.isNull())) .fetch(); } - public List findByMessageSelectorAndExecutionStatusIsActive(String messageSelector) { + public List findByMessageSelectorInActiveProcesses(String messageSelector) { QToken t = QToken.token; - return queryFactory.selectFrom(t).where(t.messageSelector.eq(messageSelector).and(t.executionStatus.eq(ExecutionStatus.ACTIVE))).fetch(); + return queryFactory.selectFrom(t) + .where(t.messageSelector.eq(messageSelector).and(t.executionStatus.ne(ExecutionStatus.SUSPENDED)).and(t.endDate.isNull())).fetch(); } - public List findByMessageSelectorInAndExecutionStatusIsActive(Collection messageSelectors) { + public List findByMessageSelectorInActiveProcesses(Collection messageSelectors) { QToken t = QToken.token; - return queryFactory.selectFrom(t).where(t.messageSelector.in(messageSelectors).and(t.executionStatus.eq(ExecutionStatus.ACTIVE))).fetch(); + return queryFactory.selectFrom(t) + .where(t.messageSelector.in(messageSelectors).and(t.executionStatus.ne(ExecutionStatus.SUSPENDED)).and(t.endDate.isNull())).fetch(); } public List findByProcessAndEndDateGreaterThanOrEquals(ru.runa.wfe.execution.Process process, Date endDate) { diff --git a/wfe-core/src/main/java/ru/runa/wfe/execution/logic/ExecutionLogic.java b/wfe-core/src/main/java/ru/runa/wfe/execution/logic/ExecutionLogic.java index 3f35a20284..8e701aef57 100644 --- a/wfe-core/src/main/java/ru/runa/wfe/execution/logic/ExecutionLogic.java +++ b/wfe-core/src/main/java/ru/runa/wfe/execution/logic/ExecutionLogic.java @@ -690,10 +690,10 @@ public List findTokensForMessageSelector(Map routingData) if (SystemProperties.isProcessExecutionMessagePredefinedSelectorEnabled()) { if (SystemProperties.isProcessExecutionMessagePredefinedSelectorOnlyStrictComplianceHandling()) { String messageSelector = Utils.getObjectMessageStrictSelector(routingData); - return tokenDao.findByMessageSelectorAndExecutionStatusIsActive(messageSelector); + return tokenDao.findByMessageSelectorInActiveProcesses(messageSelector); } else { Set messageSelectors = Utils.getObjectMessageCombinationSelectors(routingData); - return tokenDao.findByMessageSelectorInAndExecutionStatusIsActive(messageSelectors); + return tokenDao.findByMessageSelectorInActiveProcesses(messageSelectors); } } else { throw new InternalApplicationException("Method not implemented for process.execution.message.predefined.selector.enabled = false"); diff --git a/wfe-core/src/main/java/ru/runa/wfe/job/dao/JobDao.java b/wfe-core/src/main/java/ru/runa/wfe/job/dao/JobDao.java index 126dc4fa31..3c402d5edd 100644 --- a/wfe-core/src/main/java/ru/runa/wfe/job/dao/JobDao.java +++ b/wfe-core/src/main/java/ru/runa/wfe/job/dao/JobDao.java @@ -23,7 +23,7 @@ public class JobDao extends GenericDao { public List getExpiredJobs(Long limit) { QJob j = QJob.job; return queryFactory.selectFrom(j) - .where(j.dueDate.loe(new Date()).and(j.token.executionStatus.eq(ExecutionStatus.ACTIVE))) + .where(j.dueDate.loe(new Date()).and(j.token.executionStatus.ne(ExecutionStatus.SUSPENDED)).and(j.token.endDate.isNull())) .orderBy(j.dueDate.asc()) .limit(limit) .fetch(); @@ -32,7 +32,7 @@ public List getExpiredJobs(Long limit) { public Long getExpiredJobsCount() { QJob j = QJob.job; return queryFactory.selectFrom(j) - .where(j.dueDate.loe(new Date()).and(j.token.executionStatus.eq(ExecutionStatus.ACTIVE))) + .where(j.dueDate.loe(new Date()).and(j.token.executionStatus.ne(ExecutionStatus.SUSPENDED)).and(j.token.endDate.isNull())) .fetchCount(); } diff --git a/wfe-core/src/main/java/ru/runa/wfe/lang/bpmn2/TimerNode.java b/wfe-core/src/main/java/ru/runa/wfe/lang/bpmn2/TimerNode.java index e700d9bbdb..6fb184e9a1 100644 --- a/wfe-core/src/main/java/ru/runa/wfe/lang/bpmn2/TimerNode.java +++ b/wfe-core/src/main/java/ru/runa/wfe/lang/bpmn2/TimerNode.java @@ -96,15 +96,10 @@ public TaskCompletionInfo getTaskCompletionInfoIfInterrupting(ExecutionContext e public void onTimerJob(ExecutionContext executionContext, TimerJob timerJob) { try { if (actionDelegation != null) { - try { - ActionHandler actionHandler = actionDelegation.getInstance(); - log.debug("Executing delegation in " + this); - actionHandler.execute(executionContext); - executionContext.addLog(new ActionLog(this)); - } catch (Exception e) { - log.error("Failed " + this); - throw Throwables.propagate(e); - } + ActionHandler actionHandler = actionDelegation.getInstance(); + log.debug("Executing delegation in " + this); + actionHandler.execute(executionContext); + executionContext.addLog(new ActionLog(this)); } if (!getLeavingTransitions().isEmpty()) { cancelBoundaryEvent(executionContext.getToken()); diff --git a/wfe-core/src/main/java/ru/runa/wfe/task/dao/TaskDao.java b/wfe-core/src/main/java/ru/runa/wfe/task/dao/TaskDao.java index 04d9da62aa..375b2eb1a5 100644 --- a/wfe-core/src/main/java/ru/runa/wfe/task/dao/TaskDao.java +++ b/wfe-core/src/main/java/ru/runa/wfe/task/dao/TaskDao.java @@ -81,7 +81,8 @@ public List findByToken(Token token) { */ public List findUnassignedTasksInActiveProcesses() { QTask t = QTask.task; - return queryFactory.selectFrom(t).where(t.executor.isNull().and(t.token.executionStatus.ne(ExecutionStatus.SUSPENDED))).fetch(); + return queryFactory.selectFrom(t) + .where(t.executor.isNull().and(t.token.executionStatus.ne(ExecutionStatus.SUSPENDED)).and(t.token.endDate.isNull())).fetch(); } public List findUnassignedTasks() { diff --git a/wfe-service/src/main/java/ru/runa/wfe/service/impl/ReceiveMessageBean.java b/wfe-service/src/main/java/ru/runa/wfe/service/impl/ReceiveMessageBean.java index f0634dd07d..ded9430556 100644 --- a/wfe-service/src/main/java/ru/runa/wfe/service/impl/ReceiveMessageBean.java +++ b/wfe-service/src/main/java/ru/runa/wfe/service/impl/ReceiveMessageBean.java @@ -98,7 +98,7 @@ public void onMessage(Message jmsMessage) { tokens = executionLogic.findTokensForMessageSelector(routingData); log.debug("Checking " + tokens.size() + " tokens by routingData = " + routingData); } else { - tokens = tokenDao.findByNodeTypeAndExecutionStatusIsActive(NodeType.RECEIVE_MESSAGE); + tokens = tokenDao.findByNodeTypeInActiveProcesses(NodeType.RECEIVE_MESSAGE); log.debug("Checking " + tokens.size() + " tokens"); } for (Token token : tokens) { From 4210a6f2ffe4cd25c376a239ef5b8acae926e75c Mon Sep 17 00:00:00 2001 From: dofs Date: Sun, 19 Jun 2022 14:10:01 +0300 Subject: [PATCH 04/30] serializable dto for remote ejb --- .../main/java/ru/runa/wfe/report/dto/WfReportParameter.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/wfe-core/src/main/java/ru/runa/wfe/report/dto/WfReportParameter.java b/wfe-core/src/main/java/ru/runa/wfe/report/dto/WfReportParameter.java index 63c9561e41..8dd3fcb197 100644 --- a/wfe-core/src/main/java/ru/runa/wfe/report/dto/WfReportParameter.java +++ b/wfe-core/src/main/java/ru/runa/wfe/report/dto/WfReportParameter.java @@ -1,10 +1,11 @@ package ru.runa.wfe.report.dto; import com.google.common.base.Strings; - +import java.io.Serializable; import ru.runa.wfe.report.ReportParameterType; -public class WfReportParameter { +public class WfReportParameter implements Serializable { + private static final long serialVersionUID = 1L; private String userName; private String description; private String internalName; From f07ec2137b7ef70a09a824a9101a19dd6756788f Mon Sep 17 00:00:00 2001 From: Andrey Potapov Date: Thu, 23 Jun 2022 03:06:42 +0400 Subject: [PATCH 05/30] #rm2666 Reports added to datafile's import/export --- .../wfe/datafile/builder/DataFileBuilder.java | 1 + .../builder/ReportDataFileBuilder.java | 54 +++++++++++++++++++ .../runa/wfe/definition/FileDataProvider.java | 1 + .../ru/runa/wfe/report/logic/ReportLogic.java | 6 ++- .../wfe/script/logic/AdminScriptLogic.java | 2 +- .../wf/web/action/ImportDataFileAction.java | 9 ++++ 6 files changed, 71 insertions(+), 2 deletions(-) create mode 100644 wfe-core/src/main/java/ru/runa/wfe/datafile/builder/ReportDataFileBuilder.java diff --git a/wfe-core/src/main/java/ru/runa/wfe/datafile/builder/DataFileBuilder.java b/wfe-core/src/main/java/ru/runa/wfe/datafile/builder/DataFileBuilder.java index e86b5e0cb7..b6e22fef19 100644 --- a/wfe-core/src/main/java/ru/runa/wfe/datafile/builder/DataFileBuilder.java +++ b/wfe-core/src/main/java/ru/runa/wfe/datafile/builder/DataFileBuilder.java @@ -20,6 +20,7 @@ public interface DataFileBuilder extends Ordered { String PATH_TO_BOTTASK = "scripts/"; String PATH_TO_PROCESS_DEF = "processes/"; String PATH_TO_DATA_SOURCE = "data-sources/"; + String PATH_TO_REPORTS = "reports/"; /** * put data to zip archive and populate script file xml elements diff --git a/wfe-core/src/main/java/ru/runa/wfe/datafile/builder/ReportDataFileBuilder.java b/wfe-core/src/main/java/ru/runa/wfe/datafile/builder/ReportDataFileBuilder.java new file mode 100644 index 0000000000..5486ed3253 --- /dev/null +++ b/wfe-core/src/main/java/ru/runa/wfe/datafile/builder/ReportDataFileBuilder.java @@ -0,0 +1,54 @@ +package ru.runa.wfe.datafile.builder; + +import java.io.IOException; +import java.util.List; +import java.util.zip.ZipEntry; +import java.util.zip.ZipOutputStream; +import org.dom4j.Document; +import org.dom4j.Element; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import ru.runa.wfe.definition.FileDataProvider; +import ru.runa.wfe.report.logic.ReportLogic; +import ru.runa.wfe.presentation.BatchPresentation; +import ru.runa.wfe.presentation.BatchPresentationFactory; +import ru.runa.wfe.report.dto.WfReport; +import ru.runa.wfe.report.dto.WfReportParameter; + +@Component +public class ReportDataFileBuilder implements DataFileBuilder { + + @Autowired + private ReportLogic reportLogic; + + @Override + public void build(ZipOutputStream zos, Document script, ru.runa.wfe.user.User user) throws IOException { + BatchPresentation batchPresentation = BatchPresentationFactory.REPORTS.createNonPaged(); + List reports = reportLogic.getReportDefinitions(user, batchPresentation, false); + for (WfReport report : reports) { + String fileName = report.getName() + "." + FileDataProvider.REPORT_FILE; + byte[] reportLogicFile = reportLogic.getFile(user, report.getId(), ru.runa.wfe.definition.FileDataProvider.REPORT_FILE); + ZipEntry zipEntry = new ZipEntry(PATH_TO_REPORTS + fileName); + zos.putNextEntry(zipEntry); + zos.write(reportLogicFile, 0, reportLogicFile.length); + zos.closeEntry(); + Element element = script.getRootElement().addElement("deployReport", ru.runa.wfe.commons.xml.XmlUtils.RUNA_NAMESPACE); + element.addAttribute("file", PATH_TO_REPORTS + fileName); + element.addAttribute("name", report.getName()); + element.addAttribute("description", report.getDescription()); + element.addAttribute("type", report.getCategories()[0]); + for (WfReportParameter parameter : report.getParameters()) { + Element parameterElement = element.addElement("parameter"); + parameterElement.addAttribute("name", parameter.getUserName()); + parameterElement.addAttribute("innerName", parameter.getInternalName()); + parameterElement.addAttribute("type", parameter.getType().getDescription()); + //parameterElement.addAttribute("required", String.valueOf(parameter.isRequired())); + } + } + } + + @Override + public int getOrder() { + return 7; + } +} diff --git a/wfe-core/src/main/java/ru/runa/wfe/definition/FileDataProvider.java b/wfe-core/src/main/java/ru/runa/wfe/definition/FileDataProvider.java index fe7dde031e..98aef41661 100644 --- a/wfe-core/src/main/java/ru/runa/wfe/definition/FileDataProvider.java +++ b/wfe-core/src/main/java/ru/runa/wfe/definition/FileDataProvider.java @@ -2,6 +2,7 @@ public interface FileDataProvider { String PAR_FILE = "par"; + String REPORT_FILE = "jasper"; String PROCESSDEFINITION_XML_FILE_NAME = "processdefinition.xml"; String FORMS_XML_FILE_NAME = "forms.xml"; String GPD_XML_FILE_NAME = "gpd.xml"; diff --git a/wfe-core/src/main/java/ru/runa/wfe/report/logic/ReportLogic.java b/wfe-core/src/main/java/ru/runa/wfe/report/logic/ReportLogic.java index 8c2db4e8e7..38fa4be10f 100644 --- a/wfe-core/src/main/java/ru/runa/wfe/report/logic/ReportLogic.java +++ b/wfe-core/src/main/java/ru/runa/wfe/report/logic/ReportLogic.java @@ -18,7 +18,6 @@ import ru.runa.wfe.report.dto.WfReport; import ru.runa.wfe.report.dto.WfReportParameter; import ru.runa.wfe.report.impl.GetCompiledReportParametersDescription; -import ru.runa.wfe.security.AuthorizationException; import ru.runa.wfe.security.Permission; import ru.runa.wfe.security.SecuredObject; import ru.runa.wfe.security.SecuredObjectType; @@ -114,4 +113,9 @@ public ReportParameter apply(WfReportParameter input) { } return reportDefinition; } + + public byte[] getFile(User user, Long definitionId, String fileName) { + WfReport definition = getReportDefinition(user, definitionId); + return definition.getCompiledReport(); + } } diff --git a/wfe-core/src/main/java/ru/runa/wfe/script/logic/AdminScriptLogic.java b/wfe-core/src/main/java/ru/runa/wfe/script/logic/AdminScriptLogic.java index 3beea79b78..51c9900e49 100644 --- a/wfe-core/src/main/java/ru/runa/wfe/script/logic/AdminScriptLogic.java +++ b/wfe-core/src/main/java/ru/runa/wfe/script/logic/AdminScriptLogic.java @@ -32,7 +32,7 @@ public class AdminScriptLogic extends CommonLogic { @Autowired private HibernateQueryFactory queryFactory; - public void updateSript(AdminScript script) { + public void updateScript(AdminScript script) { scriptDAO.update(script); } diff --git a/wfe-web/src/main/java/ru/runa/wf/web/action/ImportDataFileAction.java b/wfe-web/src/main/java/ru/runa/wf/web/action/ImportDataFileAction.java index 34ae447e5b..a67dac574e 100644 --- a/wfe-web/src/main/java/ru/runa/wf/web/action/ImportDataFileAction.java +++ b/wfe-web/src/main/java/ru/runa/wf/web/action/ImportDataFileAction.java @@ -34,6 +34,7 @@ import ru.runa.wfe.presentation.BatchPresentationFactory; import ru.runa.wfe.relation.Relation; import ru.runa.wfe.relation.RelationPair; +import ru.runa.wfe.report.dto.WfReport; import ru.runa.wfe.script.common.WorkflowScriptDto; import ru.runa.wfe.service.delegate.Delegates; import ru.runa.wfe.user.Executor; @@ -171,6 +172,13 @@ public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServlet } ids.add(executor.getId()); } + + List reports = Delegates.getReportService().getReportDefinitions(user, + BatchPresentationFactory.REPORTS.createNonPaged(), false); + for (WfReport report : reports) { + Delegates.getReportService().undeployReport(user, report.getId() ); + } + Delegates.getExecutorService().remove(user, ids); DataSourceStorage.clear(doNotChangeInternalStoragePath); } @@ -184,6 +192,7 @@ public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServlet addMessage(request, new ActionMessage(MessagesOther.EXECUTOR_STATE_DONT_UPDATE.getKey())); return mapping.findForward(Resources.FORWARD_FAILURE); } + addMessage(request, new ActionMessage(MessagesOther.IMPORT_DATA_SUCCESS.getKey())); addMessage(request, new ActionMessage(MessagesOther.EXECUTOR_STATE_DONT_UPDATE.getKey())); return mapping.findForward(Resources.FORWARD_SUCCESS); From b99ec8c0c85fe336e55b06e76642a9ec2e8e6b5b Mon Sep 17 00:00:00 2001 From: Andrey Potapov Date: Thu, 23 Jun 2022 13:20:34 +0300 Subject: [PATCH 06/30] #rm2666 Removed comment --- .../java/ru/runa/wfe/datafile/builder/ReportDataFileBuilder.java | 1 - 1 file changed, 1 deletion(-) diff --git a/wfe-core/src/main/java/ru/runa/wfe/datafile/builder/ReportDataFileBuilder.java b/wfe-core/src/main/java/ru/runa/wfe/datafile/builder/ReportDataFileBuilder.java index 5486ed3253..62b66e29f3 100644 --- a/wfe-core/src/main/java/ru/runa/wfe/datafile/builder/ReportDataFileBuilder.java +++ b/wfe-core/src/main/java/ru/runa/wfe/datafile/builder/ReportDataFileBuilder.java @@ -42,7 +42,6 @@ public void build(ZipOutputStream zos, Document script, ru.runa.wfe.user.User us parameterElement.addAttribute("name", parameter.getUserName()); parameterElement.addAttribute("innerName", parameter.getInternalName()); parameterElement.addAttribute("type", parameter.getType().getDescription()); - //parameterElement.addAttribute("required", String.valueOf(parameter.isRequired())); } } } From d37faa8b5a8b86e1f6e69f1d40e63ea458db0ddd Mon Sep 17 00:00:00 2001 From: Dofs Date: Thu, 23 Jun 2022 14:33:29 +0300 Subject: [PATCH 07/30] excluded missed dependency --- wfe-webservice-client/pom.xml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/wfe-webservice-client/pom.xml b/wfe-webservice-client/pom.xml index 2add1f214b..826a42be1b 100644 --- a/wfe-webservice-client/pom.xml +++ b/wfe-webservice-client/pom.xml @@ -100,6 +100,10 @@ woodstox wstx-asl + + ws-commons + policy + From 6324446577e288f390254dca9729064b598a38c7 Mon Sep 17 00:00:00 2001 From: Andrey Potapov Date: Thu, 23 Jun 2022 19:05:07 +0300 Subject: [PATCH 08/30] #rm2666 Fixing code review remarks --- .../ru/runa/wfe/datafile/builder/ReportDataFileBuilder.java | 4 ++-- .../main/java/ru/runa/wfe/definition/FileDataProvider.java | 1 - .../src/main/java/ru/runa/wfe/report/logic/ReportLogic.java | 2 +- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/wfe-core/src/main/java/ru/runa/wfe/datafile/builder/ReportDataFileBuilder.java b/wfe-core/src/main/java/ru/runa/wfe/datafile/builder/ReportDataFileBuilder.java index 62b66e29f3..2d8a04c707 100644 --- a/wfe-core/src/main/java/ru/runa/wfe/datafile/builder/ReportDataFileBuilder.java +++ b/wfe-core/src/main/java/ru/runa/wfe/datafile/builder/ReportDataFileBuilder.java @@ -26,8 +26,8 @@ public void build(ZipOutputStream zos, Document script, ru.runa.wfe.user.User us BatchPresentation batchPresentation = BatchPresentationFactory.REPORTS.createNonPaged(); List reports = reportLogic.getReportDefinitions(user, batchPresentation, false); for (WfReport report : reports) { - String fileName = report.getName() + "." + FileDataProvider.REPORT_FILE; - byte[] reportLogicFile = reportLogic.getFile(user, report.getId(), ru.runa.wfe.definition.FileDataProvider.REPORT_FILE); + String fileName = report.getName() + ".jasper"; + byte[] reportLogicFile = reportLogic.getFile(user, report.getId()); ZipEntry zipEntry = new ZipEntry(PATH_TO_REPORTS + fileName); zos.putNextEntry(zipEntry); zos.write(reportLogicFile, 0, reportLogicFile.length); diff --git a/wfe-core/src/main/java/ru/runa/wfe/definition/FileDataProvider.java b/wfe-core/src/main/java/ru/runa/wfe/definition/FileDataProvider.java index 98aef41661..fe7dde031e 100644 --- a/wfe-core/src/main/java/ru/runa/wfe/definition/FileDataProvider.java +++ b/wfe-core/src/main/java/ru/runa/wfe/definition/FileDataProvider.java @@ -2,7 +2,6 @@ public interface FileDataProvider { String PAR_FILE = "par"; - String REPORT_FILE = "jasper"; String PROCESSDEFINITION_XML_FILE_NAME = "processdefinition.xml"; String FORMS_XML_FILE_NAME = "forms.xml"; String GPD_XML_FILE_NAME = "gpd.xml"; diff --git a/wfe-core/src/main/java/ru/runa/wfe/report/logic/ReportLogic.java b/wfe-core/src/main/java/ru/runa/wfe/report/logic/ReportLogic.java index 38fa4be10f..8ced06125b 100644 --- a/wfe-core/src/main/java/ru/runa/wfe/report/logic/ReportLogic.java +++ b/wfe-core/src/main/java/ru/runa/wfe/report/logic/ReportLogic.java @@ -114,7 +114,7 @@ public ReportParameter apply(WfReportParameter input) { return reportDefinition; } - public byte[] getFile(User user, Long definitionId, String fileName) { + public byte[] getFile(User user, Long definitionId) { WfReport definition = getReportDefinition(user, definitionId); return definition.getCompiledReport(); } From e3bb03cbcee6bde9b62f671238b43e404d9a9ef8 Mon Sep 17 00:00:00 2001 From: Dofs Serge Date: Wed, 29 Jun 2022 17:13:37 +0300 Subject: [PATCH 09/30] TNMS-242 add async attribute --- .../dbmigration/DbMigrationsConfig.java | 2 ++ .../impl/AddAsyncForTaskAndSubprocess.java | 29 +++++++++++++++++++ .../ru/runa/wfe/execution/NodeProcess.java | 14 ++++++++- .../ru/runa/wfe/execution/ProcessFactory.java | 4 +-- .../java/ru/runa/wfe/lang/MultiTaskNode.java | 4 +-- .../main/java/ru/runa/wfe/lang/TaskNode.java | 2 +- .../src/main/java/ru/runa/wfe/task/Task.java | 10 +++++++ .../java/ru/runa/wfe/task/TaskFactory.java | 3 +- 8 files changed, 61 insertions(+), 7 deletions(-) create mode 100644 wfe-core/src/main/java/ru/runa/wfe/commons/dbmigration/impl/AddAsyncForTaskAndSubprocess.java diff --git a/wfe-core/src/main/java/ru/runa/wfe/commons/dbmigration/DbMigrationsConfig.java b/wfe-core/src/main/java/ru/runa/wfe/commons/dbmigration/DbMigrationsConfig.java index f8e5a4cd0c..734d5b127a 100644 --- a/wfe-core/src/main/java/ru/runa/wfe/commons/dbmigration/DbMigrationsConfig.java +++ b/wfe-core/src/main/java/ru/runa/wfe/commons/dbmigration/DbMigrationsConfig.java @@ -5,6 +5,7 @@ import org.springframework.context.annotation.Configuration; import ru.runa.wfe.commons.dbmigration.impl.AddAggregatedTaskIndexPatch; import ru.runa.wfe.commons.dbmigration.impl.AddAssignDateColumnPatch; +import ru.runa.wfe.commons.dbmigration.impl.AddAsyncForTaskAndSubprocess; import ru.runa.wfe.commons.dbmigration.impl.AddBatchPresentationIsSharedPatch; import ru.runa.wfe.commons.dbmigration.impl.AddChatRoomViewPatch; import ru.runa.wfe.commons.dbmigration.impl.AddColumnForEmbeddedBotTaskFileName; @@ -160,6 +161,7 @@ public ArrayList> dbMigrations() { dbMigrations.add(DropMessageNotNullConstraintPatch.class); dbMigrations.add(RenameColumnInChatMessageRecipientPatch.class); dbMigrations.add(CorrectChatRoomViewRenameColumn.class); + dbMigrations.add(AddAsyncForTaskAndSubprocess.class); return dbMigrations; } } diff --git a/wfe-core/src/main/java/ru/runa/wfe/commons/dbmigration/impl/AddAsyncForTaskAndSubprocess.java b/wfe-core/src/main/java/ru/runa/wfe/commons/dbmigration/impl/AddAsyncForTaskAndSubprocess.java new file mode 100644 index 0000000000..386b5ee059 --- /dev/null +++ b/wfe-core/src/main/java/ru/runa/wfe/commons/dbmigration/impl/AddAsyncForTaskAndSubprocess.java @@ -0,0 +1,29 @@ +package ru.runa.wfe.commons.dbmigration.impl; + +import java.sql.Connection; +import java.sql.SQLException; +import java.sql.Statement; +import ru.runa.wfe.commons.dbmigration.DbMigration; + +public class AddAsyncForTaskAndSubprocess extends DbMigration { + + @Override + protected void executeDDLBefore() { + executeUpdates(getDDLCreateColumn("BPM_TASK", new BooleanColumnDef("ASYNC"))); + executeUpdates(getDDLCreateColumn("BPM_SUBPROCESS", new BooleanColumnDef("ASYNC"))); + } + + @Override + public void executeDML(Connection conn) throws SQLException { + try (Statement stmt = conn.createStatement()) { + stmt.executeUpdate("" + + "UPDATE BPM_TASK T SET T.ASYNC = CASE\n" + + " WHEN EXISTS(SELECT IT.ID FROM BPM_TASK IT INNER JOIN BPM_TOKEN TK ON IT.TOKEN_ID = TK.ID AND IT.NODE_ID <> TK.NODE_ID WHERE IT.ID = T.ID)\n" + + " THEN 1 ELSE 0 END"); + stmt.executeUpdate("" + + "UPDATE BPM_SUBPROCESS S SET S.ASYNC = CASE\n" + + " WHEN EXISTS(SELECT SP.ID FROM BPM_SUBPROCESS SP INNER JOIN BPM_TOKEN TK ON SP.PARENT_TOKEN_ID = TK.ID AND SP.PARENT_NODE_ID <> TK.NODE_ID WHERE SP.ID = S.ID)\n" + + " THEN 1 ELSE 0 END"); + } + } +} diff --git a/wfe-core/src/main/java/ru/runa/wfe/execution/NodeProcess.java b/wfe-core/src/main/java/ru/runa/wfe/execution/NodeProcess.java index 9704397da7..f17d34f323 100644 --- a/wfe-core/src/main/java/ru/runa/wfe/execution/NodeProcess.java +++ b/wfe-core/src/main/java/ru/runa/wfe/execution/NodeProcess.java @@ -22,6 +22,7 @@ import com.google.common.base.MoreObjects; import com.google.common.base.Objects; +import ru.runa.wfe.lang.SubprocessNode; @Entity @Table(name = "BPM_SUBPROCESS") @@ -35,17 +36,19 @@ public class NodeProcess { // TODO why = 0 for subprocess? private Integer index; private Date createDate; + private Boolean async; protected NodeProcess() { } - public NodeProcess(Node processStateNode, Token parentToken, Process subProcess, Integer index) { + public NodeProcess(SubprocessNode processStateNode, Token parentToken, Process subProcess, Integer index) { this.process = parentToken.getProcess(); this.parentToken = parentToken; this.nodeId = processStateNode.getNodeId(); this.subProcess = subProcess; this.index = index; this.createDate = new Date(); + this.async = processStateNode.isAsync(); } @Id @@ -122,6 +125,15 @@ public void setCreateDate(Date createDate) { this.createDate = createDate; } + @Column(name = "ASYNC") + public Boolean isAsync() { + return async; + } + + public void setAsync(Boolean async) { + this.async = async; + } + @Override public int hashCode() { return Objects.hashCode(id); diff --git a/wfe-core/src/main/java/ru/runa/wfe/execution/ProcessFactory.java b/wfe-core/src/main/java/ru/runa/wfe/execution/ProcessFactory.java index 401c9737c6..c7ad0c043c 100644 --- a/wfe-core/src/main/java/ru/runa/wfe/execution/ProcessFactory.java +++ b/wfe-core/src/main/java/ru/runa/wfe/execution/ProcessFactory.java @@ -18,9 +18,9 @@ import ru.runa.wfe.execution.dao.ProcessDao; import ru.runa.wfe.execution.dao.SwimlaneDao; import ru.runa.wfe.form.Interaction; -import ru.runa.wfe.lang.Node; import ru.runa.wfe.lang.ProcessDefinition; import ru.runa.wfe.lang.StartNode; +import ru.runa.wfe.lang.SubprocessNode; import ru.runa.wfe.lang.SwimlaneDefinition; import ru.runa.wfe.lang.TaskDefinition; import ru.runa.wfe.lang.Transition; @@ -102,7 +102,7 @@ private void grantProcessPermissions(ProcessDefinition processDefinition, Proces public Process createSubprocess(ExecutionContext parentExecutionContext, ProcessDefinition processDefinition, Map variables, int index, boolean validate) { Process parentProcess = parentExecutionContext.getProcess(); - Node subProcessNode = parentExecutionContext.getNode(); + SubprocessNode subProcessNode = (SubprocessNode) parentExecutionContext.getNode(); ExecutionContext subExecutionContext = createProcessInternal(processDefinition, variables, null, parentProcess, null); nodeProcessDao.create(new NodeProcess(subProcessNode, parentExecutionContext.getToken(), subExecutionContext.getProcess(), index)); if (validate) { diff --git a/wfe-core/src/main/java/ru/runa/wfe/lang/MultiTaskNode.java b/wfe-core/src/main/java/ru/runa/wfe/lang/MultiTaskNode.java index 0f0f4499d3..de07f53dfb 100644 --- a/wfe-core/src/main/java/ru/runa/wfe/lang/MultiTaskNode.java +++ b/wfe-core/src/main/java/ru/runa/wfe/lang/MultiTaskNode.java @@ -149,7 +149,7 @@ private boolean createTasksByExecutors(ExecutionContext executionContext, TaskDe log.debug("Executor is null for identity " + executorIdentity); continue; } - taskFactory.create(executionContext, taskDefinition, null, executor, tasksCounter); + taskFactory.create(executionContext, taskDefinition, null, executor, tasksCounter, async); tasksCounter++; } return tasksCounter > 0; @@ -177,7 +177,7 @@ private boolean createTasksByDiscriminator(ExecutionContext executionContext, Ta if (ignoredIndexes.contains(index)) { continue; } - taskFactory.create(executionContext, taskDefinition, swimlane, executor, index); + taskFactory.create(executionContext, taskDefinition, swimlane, executor, index, async); tasksCounter++; } return tasksCounter > 0; diff --git a/wfe-core/src/main/java/ru/runa/wfe/lang/TaskNode.java b/wfe-core/src/main/java/ru/runa/wfe/lang/TaskNode.java index 54cef76b65..315c4aa2d5 100644 --- a/wfe-core/src/main/java/ru/runa/wfe/lang/TaskNode.java +++ b/wfe-core/src/main/java/ru/runa/wfe/lang/TaskNode.java @@ -40,7 +40,7 @@ protected void execute(ExecutionContext executionContext) throws Exception { for (TaskDefinition taskDefinition : taskDefinitions) { Swimlane swimlane = getInitializedSwimlaneNotNull(executionContext, taskDefinition); // copy the swimlane assignment into the task - taskFactory.create(executionContext, taskDefinition, swimlane, swimlane.getExecutor(), null); + taskFactory.create(executionContext, taskDefinition, swimlane, swimlane.getExecutor(), null, async); } if (async) { log.debug("continue execution in async " + this); diff --git a/wfe-core/src/main/java/ru/runa/wfe/task/Task.java b/wfe-core/src/main/java/ru/runa/wfe/task/Task.java index 0401274337..22b28edb31 100644 --- a/wfe-core/src/main/java/ru/runa/wfe/task/Task.java +++ b/wfe-core/src/main/java/ru/runa/wfe/task/Task.java @@ -95,6 +95,7 @@ public class Task implements Assignable { private Process process; private Set openedByExecutorIds; private Integer index; + private Boolean async; public Task() { } @@ -261,6 +262,15 @@ public void setIndex(Integer index) { this.index = index; } + @Column(name = "ASYNC") + public Boolean isAsync() { + return async; + } + + public void setAsync(Boolean async) { + this.async = async; + } + @Transient @Override public String getSwimlaneName() { diff --git a/wfe-core/src/main/java/ru/runa/wfe/task/TaskFactory.java b/wfe-core/src/main/java/ru/runa/wfe/task/TaskFactory.java index d11daca155..725f93a629 100644 --- a/wfe-core/src/main/java/ru/runa/wfe/task/TaskFactory.java +++ b/wfe-core/src/main/java/ru/runa/wfe/task/TaskFactory.java @@ -24,7 +24,7 @@ public class TaskFactory { /** * creates a new task on the given task, in the given execution context. */ - public Task create(ExecutionContext executionContext, TaskDefinition taskDefinition, Swimlane swimlane, Executor executor, Integer index) { + public Task create(ExecutionContext executionContext, TaskDefinition taskDefinition, Swimlane swimlane, Executor executor, Integer index, Boolean isAsync) { Task task = new Task(executionContext.getToken(), taskDefinition); task.setName(ExpressionEvaluator.substitute(taskDefinition.getName(), executionContext.getVariableProvider())); task.setDescription(ExpressionEvaluator.substitute(taskDefinition.getDescription(), executionContext.getVariableProvider())); @@ -37,6 +37,7 @@ public Task create(ExecutionContext executionContext, TaskDefinition taskDefinit taskDefinition.fireEvent(executionContext, ActionEvent.TASK_CREATE); task.setSwimlane(swimlane); task.assignExecutor(executionContext, executor != null ? executor : swimlane.getExecutor(), false); + task.setAsync(isAsync); return task; } From 419e6c9a2ff8dca0d6168926f24393d91eae2f49 Mon Sep 17 00:00:00 2001 From: Gulko Roman Date: Wed, 29 Jun 2022 17:29:30 +0300 Subject: [PATCH 10/30] TNMS-471 ability to add process log from groovy --- .../java/ru/runa/wfe/audit/NodeInfoLog.java | 37 +++++++++++++++++++ .../ru/runa/wfe/audit/ProcessLogVisitor.java | 2 + .../dao/UpdateAggregatedLogOperation.java | 5 +++ .../main/java/ru/runa/wfe/audit/hierarchy.txt | 1 + .../commons/GroovyNodeInfoLogExecutor.java | 21 +++++++++++ .../wfe/commons/GroovyScriptExecutor.java | 11 ++++-- .../ru/runa/wfe/commons/ScriptExecutor.java | 13 ------- .../decision/GroovyDecisionHandler.java | 7 +--- .../wfe/extension/handler/GroovyHandler.java | 25 +++++++++---- .../impl/GroovyExpressionValidator.java | 8 +--- .../webapp/WEB-INF/classes/struts.properties | 1 + .../WEB-INF/classes/struts_ru.properties | 1 + 12 files changed, 95 insertions(+), 37 deletions(-) create mode 100644 wfe-core/src/main/java/ru/runa/wfe/audit/NodeInfoLog.java create mode 100644 wfe-core/src/main/java/ru/runa/wfe/commons/GroovyNodeInfoLogExecutor.java delete mode 100644 wfe-core/src/main/java/ru/runa/wfe/commons/ScriptExecutor.java diff --git a/wfe-core/src/main/java/ru/runa/wfe/audit/NodeInfoLog.java b/wfe-core/src/main/java/ru/runa/wfe/audit/NodeInfoLog.java new file mode 100644 index 0000000000..e8fabe444a --- /dev/null +++ b/wfe-core/src/main/java/ru/runa/wfe/audit/NodeInfoLog.java @@ -0,0 +1,37 @@ +package ru.runa.wfe.audit; + +import javax.persistence.DiscriminatorValue; +import javax.persistence.Entity; +import javax.persistence.Transient; +import ru.runa.wfe.lang.Node; + +/** + * Info log from Groovy Action. + * + * @author vromav + */ +@Entity +@DiscriminatorValue(value = "J") +public class NodeInfoLog extends NodeLog { + private static final long serialVersionUID = 1L; + + public NodeInfoLog() { + } + + public NodeInfoLog(Node node, Severity severity, String data) { + super(node); + addAttributeWithTruncation(ATTR_PARAM, data); + setSeverity(severity); + } + + @Override + public void processBy(ProcessLogVisitor visitor) { + visitor.onNodeInfoLog(this); + } + + @Override + @Transient + public Object[] getPatternArguments() { + return new Object[] { getAttribute(ATTR_PARAM) }; + } +} diff --git a/wfe-core/src/main/java/ru/runa/wfe/audit/ProcessLogVisitor.java b/wfe-core/src/main/java/ru/runa/wfe/audit/ProcessLogVisitor.java index fa69c92e3c..59de45061a 100644 --- a/wfe-core/src/main/java/ru/runa/wfe/audit/ProcessLogVisitor.java +++ b/wfe-core/src/main/java/ru/runa/wfe/audit/ProcessLogVisitor.java @@ -61,4 +61,6 @@ public interface ProcessLogVisitor { void onVariableUpdateLog(VariableUpdateLog variableUpdateLog); void onAdminActionLog(AdminActionLog adminActionLog); + + void onNodeInfoLog(NodeInfoLog nodeInfoLog); } diff --git a/wfe-core/src/main/java/ru/runa/wfe/audit/dao/UpdateAggregatedLogOperation.java b/wfe-core/src/main/java/ru/runa/wfe/audit/dao/UpdateAggregatedLogOperation.java index 55cd1ca159..287932c87d 100644 --- a/wfe-core/src/main/java/ru/runa/wfe/audit/dao/UpdateAggregatedLogOperation.java +++ b/wfe-core/src/main/java/ru/runa/wfe/audit/dao/UpdateAggregatedLogOperation.java @@ -6,6 +6,7 @@ import ru.runa.wfe.audit.CreateTimerLog; import ru.runa.wfe.audit.NodeEnterLog; import ru.runa.wfe.audit.NodeErrorLog; +import ru.runa.wfe.audit.NodeInfoLog; import ru.runa.wfe.audit.NodeLeaveLog; import ru.runa.wfe.audit.ProcessActivateLog; import ru.runa.wfe.audit.ProcessCancelLog; @@ -242,6 +243,10 @@ public void onVariableUpdateLog(VariableUpdateLog variableUpdateLog) { public void onAdminActionLog(AdminActionLog adminActionLog) { } + @Override + public void onNodeInfoLog(NodeInfoLog nodeInfoLog) { + } + private ProcessInstanceAggregatedLog getProcessInstanceLog(long processId) { QProcessInstanceAggregatedLog l = QProcessInstanceAggregatedLog.processInstanceAggregatedLog; return queryFactory.selectFrom(l).where(l.processInstanceId.eq(processId)).fetchFirst(); diff --git a/wfe-core/src/main/java/ru/runa/wfe/audit/hierarchy.txt b/wfe-core/src/main/java/ru/runa/wfe/audit/hierarchy.txt index c5bb76cbcd..e3ce63af92 100644 --- a/wfe-core/src/main/java/ru/runa/wfe/audit/hierarchy.txt +++ b/wfe-core/src/main/java/ru/runa/wfe/audit/hierarchy.txt @@ -7,6 +7,7 @@ + diff --git a/wfe-core/src/main/java/ru/runa/wfe/commons/GroovyNodeInfoLogExecutor.java b/wfe-core/src/main/java/ru/runa/wfe/commons/GroovyNodeInfoLogExecutor.java new file mode 100644 index 0000000000..5d4989c276 --- /dev/null +++ b/wfe-core/src/main/java/ru/runa/wfe/commons/GroovyNodeInfoLogExecutor.java @@ -0,0 +1,21 @@ +package ru.runa.wfe.commons; + +import ru.runa.wfe.audit.NodeInfoLog; +import ru.runa.wfe.audit.Severity; +import ru.runa.wfe.execution.ExecutionContext; + +public class GroovyNodeInfoLogExecutor { + private final ExecutionContext executionContext; + + public GroovyNodeInfoLogExecutor(ExecutionContext executionContext) { + this.executionContext = executionContext; + } + + public void debug(String message) { + executionContext.addLog(new NodeInfoLog(executionContext.getNode(), Severity.DEBUG, message)); + } + + public void info(String message) { + executionContext.addLog(new NodeInfoLog(executionContext.getNode(), Severity.INFO, message)); + } +} diff --git a/wfe-core/src/main/java/ru/runa/wfe/commons/GroovyScriptExecutor.java b/wfe-core/src/main/java/ru/runa/wfe/commons/GroovyScriptExecutor.java index 5509401062..34e798f5ff 100644 --- a/wfe-core/src/main/java/ru/runa/wfe/commons/GroovyScriptExecutor.java +++ b/wfe-core/src/main/java/ru/runa/wfe/commons/GroovyScriptExecutor.java @@ -20,14 +20,14 @@ import com.google.common.base.Throwables; import com.google.common.collect.Maps; -public class GroovyScriptExecutor implements ScriptExecutor { +public class GroovyScriptExecutor { protected static final Log log = LogFactory.getLog(GroovyScriptExecutor.class); - @Override - public Map executeScript(VariableProvider variableProvider, String script) { + public Map executeScript(VariableProvider variableProvider, String script, GroovyNodeInfoLogExecutor nodeInfoLogExecutor) { try { GroovyScriptBinding binding = createBinding(variableProvider); binding.setVariable(GroovyScriptBinding.VARIABLE_PROVIDER_VARIABLE_NAME, variableProvider); + binding.setVariable(GroovyScriptBinding.NODE_LOG_VARIABLE_NAME, nodeInfoLogExecutor); GroovyShell shell = new GroovyShell(ClassLoaderUtil.getExtensionClassLoader(), binding); shell.evaluate(script); return binding.getAdjustedVariables(); @@ -40,7 +40,6 @@ public Map executeScript(VariableProvider variableProvider, Stri } } - @Override public Object evaluateScript(VariableProvider variableProvider, String script) { try { GroovyScriptBinding binding = createBinding(variableProvider); @@ -65,6 +64,7 @@ protected GroovyScriptBinding createBinding(VariableProvider variableProvider) { public static class GroovyScriptBinding extends Binding { private final static String EXECUTION_CONTEXT_VARIABLE_NAME = "executionContext"; private final static String VARIABLE_PROVIDER_VARIABLE_NAME = "variableProvider"; + private final static String NODE_LOG_VARIABLE_NAME = "nodeLog"; private final VariableProvider variableProvider; private final Map variableScriptingNameToNameMap = Maps.newHashMap(); @@ -123,6 +123,9 @@ public Map getAdjustedVariables() { if (Objects.equal(entry.getKey(), VARIABLE_PROVIDER_VARIABLE_NAME)) { continue; } + if (Objects.equal(entry.getKey(), NODE_LOG_VARIABLE_NAME)) { + continue; + } Object oldValue = getVariableFromProcess(entry.getKey()); if (Objects.equal(oldValue, entry.getValue())) { continue; diff --git a/wfe-core/src/main/java/ru/runa/wfe/commons/ScriptExecutor.java b/wfe-core/src/main/java/ru/runa/wfe/commons/ScriptExecutor.java deleted file mode 100644 index 300b712c1d..0000000000 --- a/wfe-core/src/main/java/ru/runa/wfe/commons/ScriptExecutor.java +++ /dev/null @@ -1,13 +0,0 @@ -package ru.runa.wfe.commons; - -import java.util.Map; - -import ru.runa.wfe.var.VariableProvider; - -public interface ScriptExecutor { - - public Map executeScript(VariableProvider variableProvider, String script); - - public Object evaluateScript(VariableProvider variableProvider, String script); - -} diff --git a/wfe-core/src/main/java/ru/runa/wfe/extension/decision/GroovyDecisionHandler.java b/wfe-core/src/main/java/ru/runa/wfe/extension/decision/GroovyDecisionHandler.java index ba9846171d..40ecbb6a2f 100644 --- a/wfe-core/src/main/java/ru/runa/wfe/extension/decision/GroovyDecisionHandler.java +++ b/wfe-core/src/main/java/ru/runa/wfe/extension/decision/GroovyDecisionHandler.java @@ -1,7 +1,6 @@ package ru.runa.wfe.extension.decision; import ru.runa.wfe.commons.GroovyScriptExecutor; -import ru.runa.wfe.commons.ScriptExecutor; import ru.runa.wfe.execution.ExecutionContext; import ru.runa.wfe.extension.DecisionHandler; @@ -13,13 +12,9 @@ public void setConfiguration(String configuration) { this.configuration = configuration; } - protected ScriptExecutor getScriptExecutor() { - return new GroovyScriptExecutor(); - } - @Override public String decide(ExecutionContext executionContext) throws Exception { - Object result = getScriptExecutor().evaluateScript(executionContext.getVariableProvider(), configuration); + Object result = new GroovyScriptExecutor().evaluateScript(executionContext.getVariableProvider(), configuration); return String.valueOf(result); } diff --git a/wfe-core/src/main/java/ru/runa/wfe/extension/handler/GroovyHandler.java b/wfe-core/src/main/java/ru/runa/wfe/extension/handler/GroovyHandler.java index 34e5cf14bd..ec8c90bc41 100644 --- a/wfe-core/src/main/java/ru/runa/wfe/extension/handler/GroovyHandler.java +++ b/wfe-core/src/main/java/ru/runa/wfe/extension/handler/GroovyHandler.java @@ -1,19 +1,30 @@ package ru.runa.wfe.extension.handler; import java.util.Map; +import ru.runa.wfe.commons.GroovyNodeInfoLogExecutor; import ru.runa.wfe.commons.GroovyScriptExecutor; -import ru.runa.wfe.commons.ScriptExecutor; +import ru.runa.wfe.execution.ExecutionContext; +import ru.runa.wfe.extension.ActionHandler; +import ru.runa.wfe.task.dto.WfTask; +import ru.runa.wfe.user.User; import ru.runa.wfe.var.VariableProvider; -public class GroovyHandler extends CommonHandler { +public class GroovyHandler extends TaskHandlerBase implements ActionHandler { - @SuppressWarnings("WeakerAccess") - protected ScriptExecutor getScriptExecutor() { - return new GroovyScriptExecutor(); + @Override + public void execute(ExecutionContext context) throws Exception { + Map result = executeAction(context.getVariableProvider(), new GroovyNodeInfoLogExecutor(context)); + if (result != null) { + context.setVariableValues(result); + } } @Override - protected Map executeAction(VariableProvider variableProvider) throws Exception { - return getScriptExecutor().executeScript(variableProvider, configuration); + public Map handle(User user, VariableProvider variableProvider, WfTask task) throws Exception { + return executeAction(variableProvider, null); + } + + private Map executeAction(VariableProvider variableProvider, GroovyNodeInfoLogExecutor nodeInfoLogExecutor) { + return new GroovyScriptExecutor().executeScript(variableProvider, configuration, nodeInfoLogExecutor); } } diff --git a/wfe-core/src/main/java/ru/runa/wfe/validation/impl/GroovyExpressionValidator.java b/wfe-core/src/main/java/ru/runa/wfe/validation/impl/GroovyExpressionValidator.java index 397fd3f8f8..bd355da571 100644 --- a/wfe-core/src/main/java/ru/runa/wfe/validation/impl/GroovyExpressionValidator.java +++ b/wfe-core/src/main/java/ru/runa/wfe/validation/impl/GroovyExpressionValidator.java @@ -3,7 +3,6 @@ import com.google.common.collect.Maps; import java.util.Map; import ru.runa.wfe.commons.GroovyScriptExecutor; -import ru.runa.wfe.commons.ScriptExecutor; import ru.runa.wfe.commons.SystemProperties; import ru.runa.wfe.validation.Validator; import ru.runa.wfe.validation.ValidatorException; @@ -12,19 +11,14 @@ public class GroovyExpressionValidator extends Validator { - protected ScriptExecutor getScriptExecutor() { - return new GroovyScriptExecutor(); - } - @Override public void validate() { try { - ScriptExecutor scriptExecutor = getScriptExecutor(); String expression = getParameterNotNull(String.class, "expression"); Map variables = Maps.newHashMap(); variables.put("validator", this); VariableProvider validatorVariableProvider = new MapDelegableVariableProvider(variables, getVariableProvider()); - Object result = scriptExecutor.evaluateScript(validatorVariableProvider, expression); + Object result = new GroovyScriptExecutor().evaluateScript(validatorVariableProvider, expression); if (!Boolean.TRUE.equals(result)) { addError(); } diff --git a/wfe-web/src/main/webapp/WEB-INF/classes/struts.properties b/wfe-web/src/main/webapp/WEB-INF/classes/struts.properties index 10e05ac58d..b8cbdcfefe 100644 --- a/wfe-web/src/main/webapp/WEB-INF/classes/struts.properties +++ b/wfe-web/src/main/webapp/WEB-INF/classes/struts.properties @@ -248,6 +248,7 @@ history.log.AdminActionLog.upgrade_current_process_version = Process definition history.log.AdminActionLog.upgrade_to_next_version = Process was upgraded to next definition version by {0} history.log.AdminActionLog.upgrade_to_version = Process was upgraded from {1} to {2} definition version by {0} history.log.CreateTimerLog = Created timer for execution at {0} +history.log.NodeInfoLog = {0} history.log.NodeEnterLog = Entering node {0} history.log.NodeErrorLog = {0} history.log.NodeLeaveLog = Leaving node {0} diff --git a/wfe-web/src/main/webapp/WEB-INF/classes/struts_ru.properties b/wfe-web/src/main/webapp/WEB-INF/classes/struts_ru.properties index f3fe4f515b..3e2edec7dd 100644 --- a/wfe-web/src/main/webapp/WEB-INF/classes/struts_ru.properties +++ b/wfe-web/src/main/webapp/WEB-INF/classes/struts_ru.properties @@ -244,6 +244,7 @@ history.log.AdminActionLog.upgrade_current_process_version = \u041e\u043f\u0440\ history.log.AdminActionLog.upgrade_to_next_version = \u041f\u0440\u043e\u0446\u0435\u0441\u0441 \u043e\u0431\u043d\u043e\u0432\u043b\u0451\u043d \u0434\u043e \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0439 \u0432\u0435\u0440\u0441\u0438\u0438 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u043c {0} history.log.AdminActionLog.upgrade_to_version = \u041f\u0440\u043e\u0446\u0435\u0441\u0441 \u043e\u0431\u043d\u043e\u0432\u043b\u0451\u043d \u0434\u043e \u0441 \u0432\u0435\u0440\u0441\u0438\u0438 {1} \u0434\u043e \u0432\u0435\u0440\u0441\u0438\u0438 {2} \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u043c {0} history.log.CreateTimerActionLog = \u0412\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u043e \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0435 {0}, \u0442\u0430\u0439\u043c\u0435\u0440 \u0441\u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 {1} +history.log.NodeInfoLog = {0} history.log.NodeEnterLog = \u0423\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u043f\u0440\u0438\u0448\u043b\u043e \u0432 {0} history.log.NodeErrorLog = {0} history.log.NodeLeaveLog = \u0423\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0443\u0448\u043b\u043e \u0438\u0437 {0} From 166879b751724e70c9e3cfc8c05fa62f46682e82 Mon Sep 17 00:00:00 2001 From: Gulko Roman Date: Wed, 29 Jun 2022 18:13:03 +0300 Subject: [PATCH 11/30] TNMS-249 add MapVariableProvider to task creating --- .../java/ru/runa/wfe/lang/MultiTaskNode.java | 56 +++++++++++++++---- .../main/java/ru/runa/wfe/lang/TaskNode.java | 2 +- .../java/ru/runa/wfe/task/TaskFactory.java | 10 ++-- .../wfe/var/MapDelegableVariableProvider.java | 10 ++-- 4 files changed, 55 insertions(+), 23 deletions(-) diff --git a/wfe-core/src/main/java/ru/runa/wfe/lang/MultiTaskNode.java b/wfe-core/src/main/java/ru/runa/wfe/lang/MultiTaskNode.java index de07f53dfb..6faa53694b 100644 --- a/wfe-core/src/main/java/ru/runa/wfe/lang/MultiTaskNode.java +++ b/wfe-core/src/main/java/ru/runa/wfe/lang/MultiTaskNode.java @@ -21,24 +21,32 @@ */ package ru.runa.wfe.lang; +import com.google.common.base.Preconditions; +import com.google.common.collect.Lists; import java.util.HashMap; import java.util.HashSet; import java.util.List; - import ru.runa.wfe.commons.GroovyScriptExecutor; import ru.runa.wfe.commons.TypeConversionUtil; import ru.runa.wfe.commons.Utils; +import ru.runa.wfe.execution.ConvertToSimpleVariables; +import ru.runa.wfe.execution.ConvertToSimpleVariablesContext; +import ru.runa.wfe.execution.ConvertToSimpleVariablesResult; +import ru.runa.wfe.execution.ConvertToSimpleVariablesUnrollContext; import ru.runa.wfe.execution.ExecutionContext; import ru.runa.wfe.execution.Swimlane; import ru.runa.wfe.execution.Token; import ru.runa.wfe.lang.utils.MultiinstanceUtils; import ru.runa.wfe.task.Task; import ru.runa.wfe.user.Executor; +import ru.runa.wfe.var.MapDelegableVariableProvider; import ru.runa.wfe.var.MapVariableProvider; +import ru.runa.wfe.var.UserType; +import ru.runa.wfe.var.VariableDefinition; import ru.runa.wfe.var.VariableMapping; - -import com.google.common.base.Preconditions; -import com.google.common.collect.Lists; +import ru.runa.wfe.var.dto.WfVariable; +import ru.runa.wfe.var.format.UserTypeFormat; +import ru.runa.wfe.var.format.VariableFormatContainer; /** * is a node that relates to one or more tasks. Property signal specifies how task completion triggers continuation of execution. @@ -149,7 +157,7 @@ private boolean createTasksByExecutors(ExecutionContext executionContext, TaskDe log.debug("Executor is null for identity " + executorIdentity); continue; } - taskFactory.create(executionContext, taskDefinition, null, executor, tasksCounter, async); + taskFactory.create(executionContext, executionContext.getVariableProvider(), taskDefinition, null, executor, tasksCounter, async); tasksCounter++; } return tasksCounter > 0; @@ -177,7 +185,31 @@ private boolean createTasksByDiscriminator(ExecutionContext executionContext, Ta if (ignoredIndexes.contains(index)) { continue; } - taskFactory.create(executionContext, taskDefinition, swimlane, executor, index, async); + MapDelegableVariableProvider variableProvider = new MapDelegableVariableProvider(new HashMap<>(), executionContext.getVariableProvider()); + variableProvider.add("index", index); + for (VariableMapping m : getVariableMappings()) { + WfVariable listVariable = executionContext.getVariableProvider().getVariableNotNull(m.getName()); + List list = (List) listVariable.getValue(); + if (list != null && list.size() > index) { + VariableDefinition variableDefinition; + UserType userType = ((VariableFormatContainer) listVariable.getDefinition().getFormatNotNull()).getComponentUserType(0); + if (userType != null) { + variableDefinition = new VariableDefinition(m.getMappedName(), null, UserTypeFormat.class.getName(), userType); + } else { + String formatClassName = ((VariableFormatContainer) listVariable.getDefinition().getFormatNotNull()).getComponentClassName(0); + variableDefinition = new VariableDefinition(m.getMappedName(), null, formatClassName, null); + } + WfVariable variable = new WfVariable(variableDefinition, list.get(index)); + variableProvider.add(variable); + if (variableDefinition.getUserType() != null) { + ConvertToSimpleVariablesContext context = new ConvertToSimpleVariablesUnrollContext(variableDefinition, variable.getValueNoDefault()); + for (ConvertToSimpleVariablesResult unrolled : variableDefinition.getFormatNotNull().processBy(new ConvertToSimpleVariables(), context)) { + variableProvider.add(new WfVariable(unrolled.variableDefinition, unrolled.value)); + } + } + } + } + taskFactory.create(executionContext, variableProvider, taskDefinition, swimlane, executor, index, async); tasksCounter++; } return tasksCounter > 0; @@ -185,12 +217,12 @@ private boolean createTasksByDiscriminator(ExecutionContext executionContext, Ta public boolean isCompletionTriggersSignal(Task task) { switch (synchronizationMode) { - case FIRST: - return true; - case LAST: - return isLastTaskToComplete(task); - default: - return false; + case FIRST: + return true; + case LAST: + return isLastTaskToComplete(task); + default: + return false; } } diff --git a/wfe-core/src/main/java/ru/runa/wfe/lang/TaskNode.java b/wfe-core/src/main/java/ru/runa/wfe/lang/TaskNode.java index 315c4aa2d5..f18805882e 100644 --- a/wfe-core/src/main/java/ru/runa/wfe/lang/TaskNode.java +++ b/wfe-core/src/main/java/ru/runa/wfe/lang/TaskNode.java @@ -40,7 +40,7 @@ protected void execute(ExecutionContext executionContext) throws Exception { for (TaskDefinition taskDefinition : taskDefinitions) { Swimlane swimlane = getInitializedSwimlaneNotNull(executionContext, taskDefinition); // copy the swimlane assignment into the task - taskFactory.create(executionContext, taskDefinition, swimlane, swimlane.getExecutor(), null, async); + taskFactory.create(executionContext, executionContext.getVariableProvider(), taskDefinition, swimlane, swimlane.getExecutor(), null, async); } if (async) { log.debug("continue execution in async " + this); diff --git a/wfe-core/src/main/java/ru/runa/wfe/task/TaskFactory.java b/wfe-core/src/main/java/ru/runa/wfe/task/TaskFactory.java index 725f93a629..5966c1697d 100644 --- a/wfe-core/src/main/java/ru/runa/wfe/task/TaskFactory.java +++ b/wfe-core/src/main/java/ru/runa/wfe/task/TaskFactory.java @@ -16,6 +16,7 @@ import ru.runa.wfe.lang.jpdl.CreateTimerAction; import ru.runa.wfe.task.dao.TaskDao; import ru.runa.wfe.user.Executor; +import ru.runa.wfe.var.VariableProvider; public class TaskFactory { @Autowired @@ -24,11 +25,12 @@ public class TaskFactory { /** * creates a new task on the given task, in the given execution context. */ - public Task create(ExecutionContext executionContext, TaskDefinition taskDefinition, Swimlane swimlane, Executor executor, Integer index, Boolean isAsync) { + public Task create(ExecutionContext executionContext, VariableProvider variableProvider, TaskDefinition taskDefinition, Swimlane swimlane, + Executor executor, Integer index, Boolean isAsync) { Task task = new Task(executionContext.getToken(), taskDefinition); - task.setName(ExpressionEvaluator.substitute(taskDefinition.getName(), executionContext.getVariableProvider())); - task.setDescription(ExpressionEvaluator.substitute(taskDefinition.getDescription(), executionContext.getVariableProvider())); - task.setDeadlineDate(ExpressionEvaluator.evaluateDueDate(executionContext.getVariableProvider(), getDeadlineDuration(taskDefinition))); + task.setName(ExpressionEvaluator.substitute(taskDefinition.getName(), variableProvider)); + task.setDescription(ExpressionEvaluator.substitute(taskDefinition.getDescription(), variableProvider)); + task.setDeadlineDate(ExpressionEvaluator.evaluateDueDate(variableProvider, getDeadlineDuration(taskDefinition))); task.setDeadlineDateExpression(taskDefinition.getDeadlineDuration()); task.setIndex(index); taskDao.create(task); diff --git a/wfe-core/src/main/java/ru/runa/wfe/var/MapDelegableVariableProvider.java b/wfe-core/src/main/java/ru/runa/wfe/var/MapDelegableVariableProvider.java index 437a0ccf56..c0189f5c8a 100644 --- a/wfe-core/src/main/java/ru/runa/wfe/var/MapDelegableVariableProvider.java +++ b/wfe-core/src/main/java/ru/runa/wfe/var/MapDelegableVariableProvider.java @@ -1,14 +1,12 @@ package ru.runa.wfe.var; +import com.google.common.collect.Maps; import java.util.List; import java.util.Map; - import ru.runa.wfe.commons.TypeConversionUtil; import ru.runa.wfe.var.dto.WfVariable; import ru.runa.wfe.var.format.VariableFormatContainer; -import com.google.common.collect.Maps; - public class MapDelegableVariableProvider extends DelegableVariableProvider { protected final Map values = Maps.newHashMap(); @@ -60,12 +58,12 @@ public Object getValue(String variableName) { @Override public WfVariable getVariable(String variableName) { if (values.containsKey(variableName)) { - Object object = getValue(variableName); - if (object instanceof WfVariable) { - return (WfVariable) object; + if (values.get(variableName) instanceof WfVariable) { + return (WfVariable) values.get(variableName); } WfVariable variable = super.getVariable(variableName); if (variable != null) { + Object object = getValue(variableName); log.debug("Setting " + variable + " value to " + object); variable.setValue(object); } From 53ec87a89e8469865aef066db0ba2f2fdc48cd39 Mon Sep 17 00:00:00 2001 From: Dofs Serge Date: Thu, 7 Jul 2022 10:55:19 +0300 Subject: [PATCH 12/30] rm1962 simplified report for any database --- .../main/resources/reports/datediff.pgsql.sql | 50 ++ .../resources/reports/userTasks.mssql.jasper | Bin .../resources/reports/userTasks.mssql.jrxml | 0 .../resources/reports/userTasks.oracle.jasper | Bin 0 -> 92153 bytes .../resources/reports/userTasks.oracle.jrxml | 660 ++++++++++++++++++ .../resources/reports/userTasks.pgsql.jasper | Bin 0 -> 92165 bytes .../resources/reports/userTasks.pgsql.jrxml | 660 ++++++++++++++++++ .../resources/reports/userTasksSimple.jasper | Bin 0 -> 82127 bytes .../resources/reports/userTasksSimple.jrxml | 558 +++++++++++++++ 9 files changed, 1928 insertions(+) create mode 100644 wfe-core/src/main/resources/reports/datediff.pgsql.sql rename wfe-reports/reports/userTasks.jasper => wfe-core/src/main/resources/reports/userTasks.mssql.jasper (100%) rename wfe-reports/reports/userTasks.jrxml => wfe-core/src/main/resources/reports/userTasks.mssql.jrxml (100%) create mode 100644 wfe-core/src/main/resources/reports/userTasks.oracle.jasper create mode 100644 wfe-core/src/main/resources/reports/userTasks.oracle.jrxml create mode 100644 wfe-core/src/main/resources/reports/userTasks.pgsql.jasper create mode 100644 wfe-core/src/main/resources/reports/userTasks.pgsql.jrxml create mode 100644 wfe-core/src/main/resources/reports/userTasksSimple.jasper create mode 100644 wfe-core/src/main/resources/reports/userTasksSimple.jrxml diff --git a/wfe-core/src/main/resources/reports/datediff.pgsql.sql b/wfe-core/src/main/resources/reports/datediff.pgsql.sql new file mode 100644 index 0000000000..e4c359708d --- /dev/null +++ b/wfe-core/src/main/resources/reports/datediff.pgsql.sql @@ -0,0 +1,50 @@ +CREATE OR REPLACE FUNCTION DateDiff (units VARCHAR(30), start_t TIMESTAMP, end_t TIMESTAMP) + RETURNS INT AS $$ + DECLARE + diff_interval INTERVAL; + diff INT = 0; + years_diff INT = 0; + BEGIN + IF units IN ('yy', 'yyyy', 'year', 'mm', 'm', 'month') THEN + years_diff = DATE_PART('year', end_t) - DATE_PART('year', start_t); + + IF units IN ('yy', 'yyyy', 'year') THEN + -- SQL Server does not count full years passed (only difference between year parts) + RETURN years_diff; + ELSE + -- If end month is less than start month it will subtracted + RETURN years_diff * 12 + (DATE_PART('month', end_t) - DATE_PART('month', start_t)); + END IF; + END IF; + + -- Minus operator returns interval 'DDD days HH:MI:SS' + diff_interval = end_t - start_t; + + diff = diff + DATE_PART('day', diff_interval); + + IF units IN ('wk', 'ww', 'week') THEN + diff = diff/7; + RETURN diff; + END IF; + + IF units IN ('dd', 'd', 'day') THEN + RETURN diff; + END IF; + + diff = diff * 24 + DATE_PART('hour', diff_interval); + + IF units IN ('hh', 'hour') THEN + RETURN diff; + END IF; + + diff = diff * 60 + DATE_PART('minute', diff_interval); + + IF units IN ('mi', 'n', 'minute') THEN + RETURN diff; + END IF; + + diff = diff * 60 + DATE_PART('second', diff_interval); + + RETURN diff; + END; + $$ LANGUAGE plpgsql; diff --git a/wfe-reports/reports/userTasks.jasper b/wfe-core/src/main/resources/reports/userTasks.mssql.jasper similarity index 100% rename from wfe-reports/reports/userTasks.jasper rename to wfe-core/src/main/resources/reports/userTasks.mssql.jasper diff --git a/wfe-reports/reports/userTasks.jrxml b/wfe-core/src/main/resources/reports/userTasks.mssql.jrxml similarity index 100% rename from wfe-reports/reports/userTasks.jrxml rename to wfe-core/src/main/resources/reports/userTasks.mssql.jrxml diff --git a/wfe-core/src/main/resources/reports/userTasks.oracle.jasper b/wfe-core/src/main/resources/reports/userTasks.oracle.jasper new file mode 100644 index 0000000000000000000000000000000000000000..aad657d34575420281c9f30eaa1e5598b5775158 GIT binary patch literal 92153 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 literal 0 HcmV?d00001 diff --git a/wfe-core/src/main/resources/reports/userTasks.oracle.jrxml b/wfe-core/src/main/resources/reports/userTasks.oracle.jrxml new file mode 100644 index 0000000000..fecc7c4bca --- /dev/null +++ b/wfe-core/src/main/resources/reports/userTasks.oracle.jrxml @@ -0,0 +1,660 @@ + + + + + + + + +