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%; +}