From b7b9a4d476f076772d640cbc7fb4304d2c04556e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Peter=20Tak=C3=A1cs?=
<93127072+PeterTakacs300@users.noreply.github.com>
Date: Thu, 16 Mar 2023 05:01:40 +0100
Subject: [PATCH] IDEMPIERE-5621 - Dashboard Report ignore if parameter is
mandatory or not (#1714)
* IDEMPIERE-5621 - Dashboard Report ignore if parameter is mandatory or not
* IDEMPIERE-5621 - small fixes
* IDEMPIERE-5621 - missing javadoc for new methods
* IDEMPIERE-5621 - move scripts, list empty para, update css
---
.../oracle/202303101443_IDEMPIERE-5621.sql | 23 +++++
.../202303101443_IDEMPIERE-5621.sql | 20 ++++
.../org/compiere/model/MDashboardContent.java | 62 +++++++++++++
.../WEB-INF/src/metainfo/zk/lang-addon.xml | 2 +-
.../webui/desktop/DashboardController.java | 92 +++++++++++++------
.../theme/default/css/fragment/gadget.css.dsp | 15 +++
6 files changed, 186 insertions(+), 28 deletions(-)
create mode 100644 migration/iD10/oracle/202303101443_IDEMPIERE-5621.sql
create mode 100644 migration/iD10/postgresql/202303101443_IDEMPIERE-5621.sql
diff --git a/migration/iD10/oracle/202303101443_IDEMPIERE-5621.sql b/migration/iD10/oracle/202303101443_IDEMPIERE-5621.sql
new file mode 100644
index 0000000000..64166d40c1
--- /dev/null
+++ b/migration/iD10/oracle/202303101443_IDEMPIERE-5621.sql
@@ -0,0 +1,23 @@
+-- IDEMPIERE-5621
+SELECT register_migration_script('202303101443_IDEMPIERE-5621.sql') FROM dual;
+
+SET SQLBLANKLINES ON
+SET DEFINE OFF
+
+-- Mar 10, 2023, 2:43:41 PM CET
+INSERT INTO AD_Message (MsgType,MsgText,MsgTip,AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy,AD_Message_ID,Value,EntityType,AD_Message_UU) VALUES ('E','Fill mandatory parameters!','Mandatory parameters should be filled in the Process Parameter field of the Dashboard Content.',0,0,'Y',TO_TIMESTAMP('2023-03-10 14:43:41','YYYY-MM-DD HH24:MI:SS'),100,TO_TIMESTAMP('2023-03-10 14:43:41','YYYY-MM-DD HH24:MI:SS'),100,200824,'FillMandatoryParametersDashboard','D','e490d702-11b5-40e8-bea9-0221ae6ae3c9')
+;
+
+-- Mar 15, 2023, 2:23:02 PM CET
+UPDATE AD_Message SET MsgText='Fill mandatory parameters: {0}',Updated=TO_TIMESTAMP('2023-03-15 14:23:02','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Message_ID=200824
+;
+
+-- Mar 15, 2023, 2:27:16 PM CET
+UPDATE AD_Message SET MsgText='Fill mandatory parameters: {0}
+Mandatory parameters should be filled in the Process Parameter field of the Dashboard Content.', MsgTip=NULL,Updated=TO_TIMESTAMP('2023-03-15 14:27:16','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Message_ID=200824
+;
+
+-- Mar 15, 2023, 2:29:00 PM CET
+UPDATE AD_Message SET MsgText='Fill mandatory parameters: {0}; Mandatory parameters should be filled in the Process Parameter field of the Dashboard Content.',Updated=TO_TIMESTAMP('2023-03-15 14:29:00','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Message_ID=200824
+;
+
diff --git a/migration/iD10/postgresql/202303101443_IDEMPIERE-5621.sql b/migration/iD10/postgresql/202303101443_IDEMPIERE-5621.sql
new file mode 100644
index 0000000000..be7ab64bff
--- /dev/null
+++ b/migration/iD10/postgresql/202303101443_IDEMPIERE-5621.sql
@@ -0,0 +1,20 @@
+-- IDEMPIERE-5621
+SELECT register_migration_script('202303101443_IDEMPIERE-5621.sql') FROM dual;
+
+-- Mar 10, 2023, 2:43:41 PM CET
+INSERT INTO AD_Message (MsgType,MsgText,MsgTip,AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy,AD_Message_ID,Value,EntityType,AD_Message_UU) VALUES ('E','Fill mandatory parameters!','Mandatory parameters should be filled in the Process Parameter field of the Dashboard Content.',0,0,'Y',TO_TIMESTAMP('2023-03-10 14:43:41','YYYY-MM-DD HH24:MI:SS'),100,TO_TIMESTAMP('2023-03-10 14:43:41','YYYY-MM-DD HH24:MI:SS'),100,200824,'FillMandatoryParametersDashboard','D','e490d702-11b5-40e8-bea9-0221ae6ae3c9')
+;
+
+-- Mar 15, 2023, 2:23:02 PM CET
+UPDATE AD_Message SET MsgText='Fill mandatory parameters: {0}',Updated=TO_TIMESTAMP('2023-03-15 14:23:02','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Message_ID=200824
+;
+
+-- Mar 15, 2023, 2:27:16 PM CET
+UPDATE AD_Message SET MsgText='Fill mandatory parameters: {0}
+Mandatory parameters should be filled in the Process Parameter field of the Dashboard Content.', MsgTip=NULL,Updated=TO_TIMESTAMP('2023-03-15 14:27:16','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Message_ID=200824
+;
+
+-- Mar 15, 2023, 2:29:00 PM CET
+UPDATE AD_Message SET MsgText='Fill mandatory parameters: {0}; Mandatory parameters should be filled in the Process Parameter field of the Dashboard Content.',Updated=TO_TIMESTAMP('2023-03-15 14:29:00','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Message_ID=200824
+;
+
diff --git a/org.adempiere.base/src/org/compiere/model/MDashboardContent.java b/org.adempiere.base/src/org/compiere/model/MDashboardContent.java
index ebb468cbdb..bcf188df5d 100644
--- a/org.adempiere.base/src/org/compiere/model/MDashboardContent.java
+++ b/org.adempiere.base/src/org/compiere/model/MDashboardContent.java
@@ -5,10 +5,15 @@ package org.compiere.model;
import java.sql.ResultSet;
import java.util.ArrayList;
+import java.util.HashMap;
import java.util.List;
+import java.util.Map;
import java.util.Properties;
+import org.adempiere.exceptions.AdempiereException;
import org.compiere.util.Env;
+import org.compiere.util.Msg;
+import org.compiere.util.Util;
/**
* @author teo_sarca
@@ -172,4 +177,61 @@ public class MDashboardContent extends X_PA_DashboardContent
return (I_AD_Menu)MTable.get(getCtx(), I_AD_Menu.Table_Name)
.getPO(getAD_Menu_ID(), get_TrxName());
}
+
+ /**
+ * Parse Process Parameters
+ * @param parameters
+ * @return HashMap
+ */
+ public static Map parseProcessParameters(String parameters) {
+ Map paramMap = new HashMap();
+ if (parameters != null && parameters.trim().length() > 0) {
+ String[] params = parameters.split("[,]");
+ for (String s : params)
+ {
+ int pos = s.indexOf("=");
+ String key = s.substring(0, pos);
+ String value = s.substring(pos + 1);
+ paramMap.put(key, value);
+ }
+ }
+ return paramMap;
+ }
+
+ /**
+ * Parse all Process Parameters that are mandatory and not set
+ * @return String of comma separated parameter names
+ */
+ public String getEmptyMandatoryProcessPara() {
+ StringBuilder emptyPara = new StringBuilder();
+ int processID = getAD_Process_ID();
+ if(processID > 0) {
+ MProcess process = MProcess.get(processID);
+ Map paramMap = parseProcessParameters(getProcessParameters());
+ for(MProcessPara processPara : process.getParameters()) {
+ if(processPara.isMandatory() && Util.isEmpty(paramMap.get(processPara.getColumnName()), true)) {
+ if(!Util.isEmpty(emptyPara.toString(), true))
+ emptyPara.append(", ");
+ emptyPara.append(processPara.getColumnName());
+ }
+ }
+ }
+ return emptyPara.toString();
+ }
+
+ /*
+ * Before Save
+ * @param newRecord new
+ * @return
+ */
+ protected boolean beforeSave (boolean newRecord) {
+ // all mandatory process parameters need to be set
+ if(getAD_Process_ID() > 0) {
+ String emptyPara = getEmptyMandatoryProcessPara();
+ if(!Util.isEmpty(emptyPara)) {
+ throw new AdempiereException(Msg.getMsg(getCtx(), "FillMandatoryParametersDashboard", new Object[] {emptyPara}));
+ }
+ }
+ return true;
+ }
}
diff --git a/org.adempiere.ui.zk/WEB-INF/src/metainfo/zk/lang-addon.xml b/org.adempiere.ui.zk/WEB-INF/src/metainfo/zk/lang-addon.xml
index 7c58770368..9b34325ca7 100644
--- a/org.adempiere.ui.zk/WEB-INF/src/metainfo/zk/lang-addon.xml
+++ b/org.adempiere.ui.zk/WEB-INF/src/metainfo/zk/lang-addon.xml
@@ -57,6 +57,6 @@ Copyright (C) 2007 Ashley G Ramdass (ADempiere WebUI).
-
+
diff --git a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/desktop/DashboardController.java b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/desktop/DashboardController.java
index 7013dff455..1f6712b3aa 100644
--- a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/desktop/DashboardController.java
+++ b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/desktop/DashboardController.java
@@ -787,23 +787,27 @@ public class DashboardController implements EventListener {
Iframe iframe = new Iframe();
iframe.setSclass("dashboard-report-iframe");
iframe.setStyle("flex-grow: 1;");
- layout.appendChild(iframe);
iframe.setContent(generateReport(AD_Process_ID, dashboardContent.getAD_PrintFormat_ID(), processParameters, appDesktop, contextPath));
+ if(iframe.getContent() != null)
+ layout.appendChild(iframe);
+ else
+ layout.appendChild(createFillMandatoryLabel(dashboardContent));
Toolbar toolbar = new Toolbar();
layout.appendChild(toolbar);
btn.setLabel(Msg.getMsg(Env.getCtx(), "OpenRunDialog"));
toolbar.appendChild(btn);
- btn = new ToolBarButton();
- btn.setAttribute("AD_Process_ID", AD_Process_ID);
- btn.setAttribute("ProcessParameters", processParameters);
- btn.setAttribute("AD_PrintFormat_ID", dashboardContent.getAD_PrintFormat_ID());
- btn.addEventListener(Events.ON_CLICK, this);
- btn.setLabel(Msg.getMsg(Env.getCtx(), "ViewReportInNewTab"));
- toolbar.appendChild(new Separator("vertical"));
- toolbar.appendChild(btn);
-
+ if(iframe.getContent() != null) {
+ btn = new ToolBarButton();
+ btn.setAttribute("AD_Process_ID", AD_Process_ID);
+ btn.setAttribute("ProcessParameters", processParameters);
+ btn.setAttribute("AD_PrintFormat_ID", dashboardContent.getAD_PrintFormat_ID());
+ btn.addEventListener(Events.ON_CLICK, this);
+ btn.setLabel(Msg.getMsg(Env.getCtx(), "ViewReportInNewTab"));
+ toolbar.appendChild(new Separator("vertical"));
+ toolbar.appendChild(btn);
+ }
btn = new ToolBarButton();
if (ThemeManager.isUseFontIconForImage()) {
btn.setIconSclass("z-icon-Refresh");
@@ -1153,6 +1157,21 @@ public class DashboardController implements EventListener {
}
}
+ /**
+ * Create Fill Mandatory Process Parameters error label for the reports in dashboard
+ * @return Div
+ */
+ private Div createFillMandatoryLabel(MDashboardContent dc) {
+ Div wrapper = new Div();
+ wrapper.setSclass("fill-mandatory-process-para-wrapper");
+
+ Div msgText = new Div();
+ msgText.appendChild(new Text(Msg.getMsg(Env.getCtx(), "FillMandatoryParametersDashboard", new Object[] {dc.getEmptyMandatoryProcessPara()})));
+ LayoutUtils.addSclass("fill-mandatory-process-para-text", msgText);
+ wrapper.appendChild(msgText);
+ return wrapper;
+ }
+
private void createDashboardPreference(int AD_User_ID, int AD_Role_ID)
{
MDashboardContent[] dcs = MDashboardContentAccess.get(Env.getCtx(),AD_Role_ID, AD_User_ID, null);
@@ -1462,7 +1481,8 @@ public class DashboardController implements EventListener {
pInstance.setIsProcessing(true);
pInstance.saveEx();
try {
- fillParameter(pInstance, parameters);
+ if(!fillParameter(pInstance, parameters))
+ return null;
//
ProcessInfo pi = new ProcessInfo (process.getName(), process.getAD_Process_ID(),
AD_Table_ID, Record_ID);
@@ -1488,7 +1508,8 @@ public class DashboardController implements EventListener {
private AMedia generateReport(int AD_Process_ID, int AD_PrintFormat_ID, String parameters, IDesktop appDesktop, String contextPath) throws Exception {
ReportEngine re = runReport(AD_Process_ID, AD_PrintFormat_ID, parameters);
-
+ if(re == null)
+ return null;
File file = FileUtil.createTempFile(re.getName(), ".html");
re.createHTML(file, false, AEnv.getLanguage(Env.getCtx()), new HTMLExtension(contextPath, "rp",
appDesktop.getComponent().getUuid(), String.valueOf(AD_Process_ID)));
@@ -1500,28 +1521,32 @@ public class DashboardController implements EventListener {
new ZkReportViewerProvider().openViewer(re);
}
- private void fillParameter(MPInstance pInstance, String parameters) {
+ /**
+ * Fill Parameters
+ * @param pInstance
+ * @param parameters
+ * @return true if the parameters were filled successfully
+ */
+ private boolean fillParameter(MPInstance pInstance, String parameters) {
+ MProcessPara[] processParams = pInstance.getProcessParameters();
if (parameters != null && parameters.trim().length() > 0) {
- Map paramMap = new HashMap();
- String[] params = parameters.split("[,]");
- for (String s : params)
- {
- int pos = s.indexOf("=");
- String key = s.substring(0, pos);
- String value = s.substring(pos + 1);
- paramMap.put(key, value);
- }
- MProcessPara[] processParams = pInstance.getProcessParameters();
+ Map paramMap = MDashboardContent.parseProcessParameters(parameters);
for (int pi = 0; pi < processParams.length; pi++)
{
MPInstancePara iPara = new MPInstancePara (pInstance, processParams[pi].getSeqNo());
iPara.setParameterName(processParams[pi].getColumnName());
iPara.setInfo(processParams[pi].getName());
+ MProcessPara sPara = processParams[pi];
+
String variable = paramMap.get(iPara.getParameterName());
- if (Util.isEmpty(variable))
- continue;
+ if (Util.isEmpty(variable, true)) {
+ if(sPara.isMandatory())
+ return false; // empty mandatory parameter
+ else
+ continue;
+ }
boolean isTo = false;
@@ -1572,7 +1597,12 @@ public class DashboardController implements EventListener {
// No Value
if (value == null)
{
- continue;
+ if(sPara.isMandatory()) {
+ return false; // empty mandatory parameter
+ }
+ else {
+ continue;
+ }
}
if( DisplayType.isText(iPara.getDisplayType())
&& Util.isEmpty(String.valueOf(value))) {
@@ -1646,7 +1676,15 @@ public class DashboardController implements EventListener {
isTo = true;
}
}
- }
+ }
+ else {
+ for(MProcessPara processPara : processParams) {
+ if(processPara.isMandatory()) {
+ return false; // empty mandatory parameter
+ }
+ }
+ }
+ return true;
}
private String getDisplay(MPInstance i, MPInstancePara ip, int id) {
diff --git a/org.adempiere.ui.zk/WEB-INF/src/web/theme/default/css/fragment/gadget.css.dsp b/org.adempiere.ui.zk/WEB-INF/src/web/theme/default/css/fragment/gadget.css.dsp
index d56afddb92..263768f0f5 100644
--- a/org.adempiere.ui.zk/WEB-INF/src/web/theme/default/css/fragment/gadget.css.dsp
+++ b/org.adempiere.ui.zk/WEB-INF/src/web/theme/default/css/fragment/gadget.css.dsp
@@ -345,3 +345,18 @@
padding: 5px;
cursor: default;
}
+
+.fill-mandatory-process-para-wrapper {
+ padding: 11px;
+ display: flex;
+ flex-direction: column;
+ max-width: 500px;
+}
+
+.fill-mandatory-process-para-text {
+ background: #C62223;
+ color: white;
+ padding: 10px;
+ border-radius: 5px;
+ opacity: 90%;
+}