mirror of
https://github.com/Kingsrook/qqq.git
synced 2025-07-18 13:10:44 +00:00
SPRINT-17: updates to parent widget dropdown data, updated group bys to be objects allowing group by with custom formats
This commit is contained in:
@ -31,6 +31,9 @@ import java.util.Set;
|
|||||||
import com.kingsrook.qqq.backend.core.actions.ActionHelper;
|
import com.kingsrook.qqq.backend.core.actions.ActionHelper;
|
||||||
import com.kingsrook.qqq.backend.core.actions.values.SearchPossibleValueSourceAction;
|
import com.kingsrook.qqq.backend.core.actions.values.SearchPossibleValueSourceAction;
|
||||||
import com.kingsrook.qqq.backend.core.exceptions.QException;
|
import com.kingsrook.qqq.backend.core.exceptions.QException;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.actions.tables.query.QCriteriaOperator;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.actions.tables.query.QFilterCriteria;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.actions.tables.query.QQueryFilter;
|
||||||
import com.kingsrook.qqq.backend.core.model.actions.values.SearchPossibleValueSourceInput;
|
import com.kingsrook.qqq.backend.core.model.actions.values.SearchPossibleValueSourceInput;
|
||||||
import com.kingsrook.qqq.backend.core.model.actions.values.SearchPossibleValueSourceOutput;
|
import com.kingsrook.qqq.backend.core.model.actions.values.SearchPossibleValueSourceOutput;
|
||||||
import com.kingsrook.qqq.backend.core.model.actions.widgets.RenderWidgetInput;
|
import com.kingsrook.qqq.backend.core.model.actions.widgets.RenderWidgetInput;
|
||||||
@ -40,6 +43,7 @@ import com.kingsrook.qqq.backend.core.model.metadata.dashboard.ParentWidgetMetaD
|
|||||||
import com.kingsrook.qqq.backend.core.model.metadata.possiblevalues.QPossibleValue;
|
import com.kingsrook.qqq.backend.core.model.metadata.possiblevalues.QPossibleValue;
|
||||||
import com.kingsrook.qqq.backend.core.model.metadata.possiblevalues.QPossibleValueSource;
|
import com.kingsrook.qqq.backend.core.model.metadata.possiblevalues.QPossibleValueSource;
|
||||||
import com.kingsrook.qqq.backend.core.utils.CollectionUtils;
|
import com.kingsrook.qqq.backend.core.utils.CollectionUtils;
|
||||||
|
import com.kingsrook.qqq.backend.core.utils.StringUtils;
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
@ -68,15 +72,42 @@ public class ParentWidgetRenderer extends AbstractWidgetRenderer
|
|||||||
List<List<Map<String, String>>> pvsData = new ArrayList<>();
|
List<List<Map<String, String>>> pvsData = new ArrayList<>();
|
||||||
List<String> pvsLabels = new ArrayList<>();
|
List<String> pvsLabels = new ArrayList<>();
|
||||||
List<String> pvsNames = new ArrayList<>();
|
List<String> pvsNames = new ArrayList<>();
|
||||||
for(String possibleValueSourceName : CollectionUtils.nonNullList(metaData.getPossibleValueNameList()))
|
for(ParentWidgetMetaData.DropdownData dropdownData : CollectionUtils.nonNullList(metaData.getDropdowns()))
|
||||||
{
|
{
|
||||||
QPossibleValueSource possibleValueSource = input.getInstance().getPossibleValueSource(possibleValueSourceName);
|
String possibleValueSourceName = dropdownData.getPossibleValueSourceName();
|
||||||
pvsLabels.add(possibleValueSource.getLabel() != null ? possibleValueSource.getLabel() : possibleValueSourceName);
|
QPossibleValueSource possibleValueSource = input.getInstance().getPossibleValueSource(possibleValueSourceName);
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// this looks complicated, but is just look for a label in the dropdown data and if found use it, //
|
||||||
|
// otherwise look for label in PVS and if found use that, otherwise just use the PVS name //
|
||||||
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
pvsLabels.add(dropdownData.getLabel() != null ? dropdownData.getLabel() : (possibleValueSource.getLabel() != null ? possibleValueSource.getLabel() : possibleValueSourceName));
|
||||||
pvsNames.add(possibleValueSourceName);
|
pvsNames.add(possibleValueSourceName);
|
||||||
|
|
||||||
SearchPossibleValueSourceInput pvsInput = new SearchPossibleValueSourceInput(input.getInstance());
|
SearchPossibleValueSourceInput pvsInput = new SearchPossibleValueSourceInput(input.getInstance());
|
||||||
pvsInput.setSession(input.getSession());
|
pvsInput.setSession(input.getSession());
|
||||||
pvsInput.setPossibleValueSourceName(possibleValueSourceName);
|
pvsInput.setPossibleValueSourceName(possibleValueSourceName);
|
||||||
|
|
||||||
|
if(dropdownData.getForeignKeyFieldName() != null)
|
||||||
|
{
|
||||||
|
////////////////////////////////////////
|
||||||
|
// look for an id in the query params //
|
||||||
|
////////////////////////////////////////
|
||||||
|
Integer id = null;
|
||||||
|
if(input.getQueryParams() != null && input.getQueryParams().containsKey("id") && StringUtils.hasContent(input.getQueryParams().get("id")))
|
||||||
|
{
|
||||||
|
id = Integer.parseInt(input.getQueryParams().get("id"));
|
||||||
|
}
|
||||||
|
if(id != null)
|
||||||
|
{
|
||||||
|
pvsInput.setDefaultQueryFilter(new QQueryFilter().withCriteria(
|
||||||
|
new QFilterCriteria(
|
||||||
|
dropdownData.getForeignKeyFieldName(),
|
||||||
|
QCriteriaOperator.EQUALS,
|
||||||
|
id)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
SearchPossibleValueSourceOutput output = new SearchPossibleValueSourceAction().execute(pvsInput);
|
SearchPossibleValueSourceOutput output = new SearchPossibleValueSourceAction().execute(pvsInput);
|
||||||
|
|
||||||
List<Map<String, String>> dropdownOptionList = new ArrayList<>();
|
List<Map<String, String>> dropdownOptionList = new ArrayList<>();
|
||||||
|
@ -38,7 +38,7 @@ public class AggregateInput extends AbstractTableActionInput
|
|||||||
{
|
{
|
||||||
private QQueryFilter filter;
|
private QQueryFilter filter;
|
||||||
private List<Aggregate> aggregates;
|
private List<Aggregate> aggregates;
|
||||||
private List<String> groupByFieldNames;
|
private List<GroupBy> groupBys = new ArrayList<>();
|
||||||
|
|
||||||
private List<QueryJoin> queryJoins = null;
|
private List<QueryJoin> queryJoins = null;
|
||||||
|
|
||||||
@ -148,50 +148,50 @@ public class AggregateInput extends AbstractTableActionInput
|
|||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
** Getter for groupByFieldNames
|
** Getter for groupBys
|
||||||
**
|
**
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
public List<String> getGroupByFieldNames()
|
public List<GroupBy> getGroupBys()
|
||||||
{
|
{
|
||||||
return groupByFieldNames;
|
return groupBys;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
** Setter for groupByFieldNames
|
** Setter for groupBys
|
||||||
**
|
**
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
public void setGroupByFieldNames(List<String> groupByFieldNames)
|
public void setGroupBys(List<GroupBy> groupBys)
|
||||||
{
|
{
|
||||||
this.groupByFieldNames = groupByFieldNames;
|
this.groupBys = groupBys;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
** Fluent setter for groupByFieldNames
|
** Fluent setter for groupBys
|
||||||
**
|
**
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
public AggregateInput withGroupByFieldNames(List<String> groupByFieldNames)
|
public AggregateInput withGroupBys(List<GroupBy> groupBys)
|
||||||
{
|
{
|
||||||
this.groupByFieldNames = groupByFieldNames;
|
this.groupBys = groupBys;
|
||||||
return (this);
|
return (this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
** Fluent setter for groupByFieldNames
|
** Fluent setter for groupBys
|
||||||
**
|
**
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
public AggregateInput withGroupByFieldName(String groupByFieldName)
|
public AggregateInput withGroupBy(GroupBy groupBy)
|
||||||
{
|
{
|
||||||
if(this.groupByFieldNames == null)
|
if(this.groupBys == null)
|
||||||
{
|
{
|
||||||
this.groupByFieldNames = new ArrayList<>();
|
this.groupBys = new ArrayList<>();
|
||||||
}
|
}
|
||||||
this.groupByFieldNames.add(groupByFieldName);
|
this.groupBys.add(groupBy);
|
||||||
return (this);
|
return (this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -33,7 +33,7 @@ import java.util.Map;
|
|||||||
public class AggregateResult
|
public class AggregateResult
|
||||||
{
|
{
|
||||||
private Map<Aggregate, Serializable> aggregateValues = new LinkedHashMap<>();
|
private Map<Aggregate, Serializable> aggregateValues = new LinkedHashMap<>();
|
||||||
private Map<String, Serializable> groupByValues = new LinkedHashMap<>();
|
private Map<GroupBy, Serializable> groupByValues = new LinkedHashMap<>();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -101,7 +101,7 @@ public class AggregateResult
|
|||||||
** Getter for groupByValues
|
** Getter for groupByValues
|
||||||
**
|
**
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
public Map<String, Serializable> getGroupByValues()
|
public Map<GroupBy, Serializable> getGroupByValues()
|
||||||
{
|
{
|
||||||
return groupByValues;
|
return groupByValues;
|
||||||
}
|
}
|
||||||
@ -112,7 +112,7 @@ public class AggregateResult
|
|||||||
** Setter for groupByValues
|
** Setter for groupByValues
|
||||||
**
|
**
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
public void setGroupByValues(Map<String, Serializable> groupByValues)
|
public void setGroupByValues(Map<GroupBy, Serializable> groupByValues)
|
||||||
{
|
{
|
||||||
this.groupByValues = groupByValues;
|
this.groupByValues = groupByValues;
|
||||||
}
|
}
|
||||||
@ -123,7 +123,7 @@ public class AggregateResult
|
|||||||
** Fluent setter for groupByValues
|
** Fluent setter for groupByValues
|
||||||
**
|
**
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
public AggregateResult withGroupByValues(Map<String, Serializable> groupByValues)
|
public AggregateResult withGroupByValues(Map<GroupBy, Serializable> groupByValues)
|
||||||
{
|
{
|
||||||
this.groupByValues = groupByValues;
|
this.groupByValues = groupByValues;
|
||||||
return (this);
|
return (this);
|
||||||
@ -135,13 +135,13 @@ public class AggregateResult
|
|||||||
** Fluent setter for groupByValues
|
** Fluent setter for groupByValues
|
||||||
**
|
**
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
public AggregateResult withGroupByValue(String fieldName, Serializable value)
|
public AggregateResult withGroupByValue(GroupBy groupBy, Serializable value)
|
||||||
{
|
{
|
||||||
if(this.groupByValues == null)
|
if(this.groupByValues == null)
|
||||||
{
|
{
|
||||||
this.groupByValues = new LinkedHashMap<>();
|
this.groupByValues = new LinkedHashMap<>();
|
||||||
}
|
}
|
||||||
this.groupByValues.put(fieldName, value);
|
this.groupByValues.put(groupBy, value);
|
||||||
return (this);
|
return (this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -150,9 +150,9 @@ public class AggregateResult
|
|||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
**
|
**
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
public Serializable getGroupByValue(String fieldName)
|
public Serializable getGroupByValue(GroupBy groupBy)
|
||||||
{
|
{
|
||||||
return (this.groupByValues.get(fieldName));
|
return (this.groupByValues.get(groupBy));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,152 @@
|
|||||||
|
/*
|
||||||
|
* QQQ - Low-code Application Framework for Engineers.
|
||||||
|
* Copyright (C) 2021-2022. Kingsrook, LLC
|
||||||
|
* 651 N Broad St Ste 205 # 6917 | Middletown DE 19709 | United States
|
||||||
|
* contact@kingsrook.com
|
||||||
|
* https://github.com/Kingsrook/
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as
|
||||||
|
* published by the Free Software Foundation, either version 3 of the
|
||||||
|
* License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.kingsrook.qqq.backend.core.model.actions.tables.aggregate;
|
||||||
|
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.metadata.fields.QFieldType;
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public class GroupBy implements Serializable
|
||||||
|
{
|
||||||
|
private QFieldType type;
|
||||||
|
private String fieldName;
|
||||||
|
private String formatString;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public GroupBy(QFieldType type, String fieldName, String formatString)
|
||||||
|
{
|
||||||
|
this.type = type;
|
||||||
|
this.fieldName = fieldName;
|
||||||
|
this.formatString = formatString;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Getter for type
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public QFieldType getType()
|
||||||
|
{
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Setter for type
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public void setType(QFieldType type)
|
||||||
|
{
|
||||||
|
this.type = type;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Fluent setter for type
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public GroupBy withType(QFieldType type)
|
||||||
|
{
|
||||||
|
this.type = type;
|
||||||
|
return (this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Getter for fieldName
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public String getFieldName()
|
||||||
|
{
|
||||||
|
return fieldName;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Setter for fieldName
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public void setFieldName(String fieldName)
|
||||||
|
{
|
||||||
|
this.fieldName = fieldName;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Fluent setter for fieldName
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public GroupBy withFieldName(String fieldName)
|
||||||
|
{
|
||||||
|
this.fieldName = fieldName;
|
||||||
|
return (this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Getter for formatString
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public String getFormatString()
|
||||||
|
{
|
||||||
|
return formatString;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Setter for formatString
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public void setFormatString(String formatString)
|
||||||
|
{
|
||||||
|
this.formatString = formatString;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Fluent setter for formatString
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public GroupBy withFormatString(String formatString)
|
||||||
|
{
|
||||||
|
this.formatString = formatString;
|
||||||
|
return (this);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,123 @@
|
|||||||
|
/*
|
||||||
|
* QQQ - Low-code Application Framework for Engineers.
|
||||||
|
* Copyright (C) 2021-2022. Kingsrook, LLC
|
||||||
|
* 651 N Broad St Ste 205 # 6917 | Middletown DE 19709 | United States
|
||||||
|
* contact@kingsrook.com
|
||||||
|
* https://github.com/Kingsrook/
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as
|
||||||
|
* published by the Free Software Foundation, either version 3 of the
|
||||||
|
* License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.kingsrook.qqq.backend.core.model.actions.tables.aggregate;
|
||||||
|
|
||||||
|
|
||||||
|
import com.kingsrook.qqq.backend.core.model.actions.tables.query.QFilterOrderBy;
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Bean representing an element of a query order-by clause - ordering by a
|
||||||
|
** group by
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public class QFilterOrderByGroupBy extends QFilterOrderBy implements Cloneable
|
||||||
|
{
|
||||||
|
private GroupBy groupBy;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
@Override
|
||||||
|
public QFilterOrderByGroupBy clone()
|
||||||
|
{
|
||||||
|
return (QFilterOrderByGroupBy) super.clone();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Default no-arg constructor
|
||||||
|
*******************************************************************************/
|
||||||
|
public QFilterOrderByGroupBy()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Constructor that sets groupBy, but leaves default for isAscending (true)
|
||||||
|
*******************************************************************************/
|
||||||
|
public QFilterOrderByGroupBy(GroupBy groupBy)
|
||||||
|
{
|
||||||
|
this.groupBy = groupBy;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Constructor that takes groupBy and isAscending.
|
||||||
|
*******************************************************************************/
|
||||||
|
public QFilterOrderByGroupBy(GroupBy groupBy, boolean isAscending)
|
||||||
|
{
|
||||||
|
this.groupBy = groupBy;
|
||||||
|
setIsAscending(isAscending);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Getter for groupBy
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public GroupBy getGroupBy()
|
||||||
|
{
|
||||||
|
return groupBy;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Setter for groupBy
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public void setGroupBy(GroupBy groupBy)
|
||||||
|
{
|
||||||
|
this.groupBy = groupBy;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Fluent setter for groupBy
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public QFilterOrderByGroupBy withGroupBy(GroupBy groupBy)
|
||||||
|
{
|
||||||
|
this.groupBy = groupBy;
|
||||||
|
return (this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
@Override
|
||||||
|
public String toString()
|
||||||
|
{
|
||||||
|
return (groupBy + " " + (getIsAscending() ? "ASC" : "DESC"));
|
||||||
|
}
|
||||||
|
}
|
@ -41,9 +41,21 @@ public class ChartData implements QWidget
|
|||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
private String title;
|
private String title;
|
||||||
private String description;
|
private String description;
|
||||||
private Data chartData;
|
private List<String> colors;
|
||||||
|
private Data chartData;
|
||||||
|
private boolean isCurrency = false;
|
||||||
|
private int height;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public ChartData()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -176,6 +188,74 @@ public class ChartData implements QWidget
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Getter for isCurrency
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public boolean getIsCurrency()
|
||||||
|
{
|
||||||
|
return isCurrency;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Setter for isCurrency
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public void setIsCurrency(boolean isCurrency)
|
||||||
|
{
|
||||||
|
this.isCurrency = isCurrency;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Fluent setter for isCurrency
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public ChartData withIsCurrency(boolean isCurrency)
|
||||||
|
{
|
||||||
|
this.isCurrency = isCurrency;
|
||||||
|
return (this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Getter for height
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public int getHeight()
|
||||||
|
{
|
||||||
|
return height;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Setter for height
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public void setHeight(int height)
|
||||||
|
{
|
||||||
|
this.height = height;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Fluent setter for height
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public ChartData withHeight(int height)
|
||||||
|
{
|
||||||
|
this.height = height;
|
||||||
|
return (this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
**
|
**
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
@ -224,9 +304,13 @@ public class ChartData implements QWidget
|
|||||||
** Getter for datasets
|
** Getter for datasets
|
||||||
**
|
**
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
public Dataset getDataset()
|
public List<Dataset> getDatasets()
|
||||||
{
|
{
|
||||||
return dataset;
|
if(dataset != null)
|
||||||
|
{
|
||||||
|
return List.of(dataset);
|
||||||
|
}
|
||||||
|
return List.of();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -260,6 +344,7 @@ public class ChartData implements QWidget
|
|||||||
public static class Dataset
|
public static class Dataset
|
||||||
{
|
{
|
||||||
private String label;
|
private String label;
|
||||||
|
private String color;
|
||||||
private List<Number> data;
|
private List<Number> data;
|
||||||
|
|
||||||
|
|
||||||
@ -286,6 +371,40 @@ public class ChartData implements QWidget
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Getter for color
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public String getColor()
|
||||||
|
{
|
||||||
|
return color;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Setter for color
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public void setColor(String color)
|
||||||
|
{
|
||||||
|
this.color = color;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Fluent setter for color
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public Dataset withColor(String color)
|
||||||
|
{
|
||||||
|
this.color = color;
|
||||||
|
return (this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
** Fluent setter for label
|
** Fluent setter for label
|
||||||
**
|
**
|
||||||
|
@ -44,8 +44,9 @@ public class LineChartData implements QWidget
|
|||||||
};
|
};
|
||||||
*/
|
*/
|
||||||
|
|
||||||
private String title;
|
private String title;
|
||||||
private Data chartData;
|
private Data chartData;
|
||||||
|
private boolean isYAxisCurrency = false;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -151,6 +152,40 @@ public class LineChartData implements QWidget
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Getter for isYAxisCurrency
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public boolean getIsYAxisCurrency()
|
||||||
|
{
|
||||||
|
return isYAxisCurrency;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Setter for isYAxisCurrency
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public void setIsYAxisCurrency(boolean isYAxisCurrency)
|
||||||
|
{
|
||||||
|
this.isYAxisCurrency = isYAxisCurrency;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Fluent setter for isYAxisCurrency
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public LineChartData withIsYAxisCurrency(boolean isYAxisCurrency)
|
||||||
|
{
|
||||||
|
this.isYAxisCurrency = isYAxisCurrency;
|
||||||
|
return (this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
**
|
**
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
|
@ -38,17 +38,18 @@ public class StatisticsData implements QWidget
|
|||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
private String title;
|
private String title;
|
||||||
private int count;
|
private Number count;
|
||||||
private Number percentageAmount;
|
private Number percentageAmount;
|
||||||
private String percentageLabel;
|
private String percentageLabel;
|
||||||
|
private boolean isCurrency = false;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
**
|
**
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
public StatisticsData(String title, int count, Number percentageAmount, String percentageLabel)
|
public StatisticsData(String title, Number count, Number percentageAmount, String percentageLabel)
|
||||||
{
|
{
|
||||||
this.title = title;
|
this.title = title;
|
||||||
this.count = count;
|
this.count = count;
|
||||||
@ -107,7 +108,7 @@ public class StatisticsData implements QWidget
|
|||||||
** Getter for count
|
** Getter for count
|
||||||
**
|
**
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
public int getCount()
|
public Number getCount()
|
||||||
{
|
{
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
@ -118,7 +119,7 @@ public class StatisticsData implements QWidget
|
|||||||
** Setter for count
|
** Setter for count
|
||||||
**
|
**
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
public void setCount(int count)
|
public void setCount(Number count)
|
||||||
{
|
{
|
||||||
this.count = count;
|
this.count = count;
|
||||||
}
|
}
|
||||||
@ -129,7 +130,7 @@ public class StatisticsData implements QWidget
|
|||||||
** Fluent setter for count
|
** Fluent setter for count
|
||||||
**
|
**
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
public StatisticsData withCount(int count)
|
public StatisticsData withCount(Number count)
|
||||||
{
|
{
|
||||||
this.count = count;
|
this.count = count;
|
||||||
return (this);
|
return (this);
|
||||||
@ -203,4 +204,38 @@ public class StatisticsData implements QWidget
|
|||||||
return (this);
|
return (this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Getter for isCurrency
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public boolean getIsCurrency()
|
||||||
|
{
|
||||||
|
return isCurrency;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Setter for isCurrency
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public void setIsCurrency(boolean isCurrency)
|
||||||
|
{
|
||||||
|
this.isCurrency = isCurrency;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Fluent setter for isCurrency
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public StatisticsData withIsCurrency(boolean isCurrency)
|
||||||
|
{
|
||||||
|
this.isCurrency = isCurrency;
|
||||||
|
return (this);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -27,9 +27,11 @@ package com.kingsrook.qqq.backend.core.model.dashboard.widgets;
|
|||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
public enum WidgetType
|
public enum WidgetType
|
||||||
{
|
{
|
||||||
|
BAR_CHART("barChart"),
|
||||||
CHART("chart"),
|
CHART("chart"),
|
||||||
CHILD_RECORD_LIST("childRecordList"),
|
CHILD_RECORD_LIST("childRecordList"),
|
||||||
GENERIC("generic"),
|
GENERIC("generic"),
|
||||||
|
HORIZONTAL_BAR_CHART("horizontalBarChart"),
|
||||||
HTML("html"),
|
HTML("html"),
|
||||||
LINE_CHART("lineChart"),
|
LINE_CHART("lineChart"),
|
||||||
LOCATION("location"),
|
LOCATION("location"),
|
||||||
|
@ -31,10 +31,11 @@ import java.util.List;
|
|||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
public class ParentWidgetMetaData extends QWidgetMetaData implements QWidgetMetaDataInterface
|
public class ParentWidgetMetaData extends QWidgetMetaData implements QWidgetMetaDataInterface
|
||||||
{
|
{
|
||||||
private String title;
|
private String title;
|
||||||
private List<String> possibleValueNameList;
|
private List<String> possibleValueNameList;
|
||||||
private List<String> childWidgetNameList;
|
private List<String> childWidgetNameList;
|
||||||
private List<String> childProcessNameList;
|
private List<String> childProcessNameList;
|
||||||
|
private List<DropdownData> dropdowns;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -172,4 +173,154 @@ public class ParentWidgetMetaData extends QWidgetMetaData implements QWidgetMeta
|
|||||||
return (this);
|
return (this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Getter for dropdowns
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public List<DropdownData> getDropdowns()
|
||||||
|
{
|
||||||
|
return dropdowns;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Setter for dropdowns
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public void setDropdowns(List<DropdownData> dropdowns)
|
||||||
|
{
|
||||||
|
this.dropdowns = dropdowns;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Fluent setter for dropdowns
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public ParentWidgetMetaData withDropdowns(List<DropdownData> dropdowns)
|
||||||
|
{
|
||||||
|
this.dropdowns = dropdowns;
|
||||||
|
return (this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** inner class for specifying details about dropdown fields on a parent widget
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public static class DropdownData
|
||||||
|
{
|
||||||
|
private String possibleValueSourceName;
|
||||||
|
private String foreignKeyFieldName;
|
||||||
|
private String label;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Getter for possibleValueSourceName
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public String getPossibleValueSourceName()
|
||||||
|
{
|
||||||
|
return possibleValueSourceName;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Setter for possibleValueSourceName
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public void setPossibleValueSourceName(String possibleValueSourceName)
|
||||||
|
{
|
||||||
|
this.possibleValueSourceName = possibleValueSourceName;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Fluent setter for possibleValueSourceName
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public DropdownData withPossibleValueSourceName(String possibleValueSourceName)
|
||||||
|
{
|
||||||
|
this.possibleValueSourceName = possibleValueSourceName;
|
||||||
|
return (this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Getter for foreignKeyFieldName
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public String getForeignKeyFieldName()
|
||||||
|
{
|
||||||
|
return foreignKeyFieldName;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Setter for foreignKeyFieldName
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public void setForeignKeyFieldName(String foreignKeyFieldName)
|
||||||
|
{
|
||||||
|
this.foreignKeyFieldName = foreignKeyFieldName;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Fluent setter for foreignKeyFieldName
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public DropdownData withForeignKeyFieldName(String foreignKeyFieldName)
|
||||||
|
{
|
||||||
|
this.foreignKeyFieldName = foreignKeyFieldName;
|
||||||
|
return (this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Getter for label
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public String getLabel()
|
||||||
|
{
|
||||||
|
return label;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Setter for label
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public void setLabel(String label)
|
||||||
|
{
|
||||||
|
this.label = label;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Fluent setter for label
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public DropdownData withLabel(String label)
|
||||||
|
{
|
||||||
|
this.label = label;
|
||||||
|
return (this);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -197,6 +197,23 @@ public class GeneralProcessUtils
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Query to get one entity by a unique key value. That field can be the primary
|
||||||
|
** key, or any other field on the table. Note, if multiple rows do match the value,
|
||||||
|
** only 1 (determined in an unspecified way) is returned.
|
||||||
|
*******************************************************************************/
|
||||||
|
public static <T extends QRecordEntity> Optional<T> getEntityByField(AbstractActionInput parentActionInput, String tableName, String fieldName, Serializable fieldValue, Class<T> entityClass) throws QException
|
||||||
|
{
|
||||||
|
Optional<QRecord> optionalQRecord = getRecordByField(parentActionInput, tableName, fieldName, fieldValue);
|
||||||
|
if(optionalQRecord.isPresent())
|
||||||
|
{
|
||||||
|
return (Optional.of(QRecordEntity.fromQRecord(entityClass, optionalQRecord.get())));
|
||||||
|
}
|
||||||
|
return (Optional.empty());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
** Query to get one record by a unique key value.
|
** Query to get one record by a unique key value.
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
|
@ -37,7 +37,9 @@ import com.kingsrook.qqq.backend.core.actions.interfaces.QActionInterface;
|
|||||||
import com.kingsrook.qqq.backend.core.exceptions.QException;
|
import com.kingsrook.qqq.backend.core.exceptions.QException;
|
||||||
import com.kingsrook.qqq.backend.core.model.actions.AbstractTableActionInput;
|
import com.kingsrook.qqq.backend.core.model.actions.AbstractTableActionInput;
|
||||||
import com.kingsrook.qqq.backend.core.model.actions.tables.aggregate.Aggregate;
|
import com.kingsrook.qqq.backend.core.model.actions.tables.aggregate.Aggregate;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.actions.tables.aggregate.GroupBy;
|
||||||
import com.kingsrook.qqq.backend.core.model.actions.tables.aggregate.QFilterOrderByAggregate;
|
import com.kingsrook.qqq.backend.core.model.actions.tables.aggregate.QFilterOrderByAggregate;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.actions.tables.aggregate.QFilterOrderByGroupBy;
|
||||||
import com.kingsrook.qqq.backend.core.model.actions.tables.query.JoinsContext;
|
import com.kingsrook.qqq.backend.core.model.actions.tables.query.JoinsContext;
|
||||||
import com.kingsrook.qqq.backend.core.model.actions.tables.query.QFilterCriteria;
|
import com.kingsrook.qqq.backend.core.model.actions.tables.query.QFilterCriteria;
|
||||||
import com.kingsrook.qqq.backend.core.model.actions.tables.query.QFilterOrderBy;
|
import com.kingsrook.qqq.backend.core.model.actions.tables.query.QFilterOrderBy;
|
||||||
@ -123,7 +125,7 @@ public abstract class AbstractRDBMSAction implements QActionInterface
|
|||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
protected Serializable scrubValue(QFieldMetaData field, Serializable value, boolean isInsert)
|
protected Serializable scrubValue(QFieldMetaData field, Serializable value, boolean isInsert)
|
||||||
{
|
{
|
||||||
if("".equals(value))
|
if("" .equals(value))
|
||||||
{
|
{
|
||||||
QFieldType type = field.getType();
|
QFieldType type = field.getType();
|
||||||
if(type.equals(QFieldType.INTEGER) || type.equals(QFieldType.DECIMAL) || type.equals(QFieldType.DATE) || type.equals(QFieldType.DATE_TIME) || type.equals(QFieldType.BOOLEAN))
|
if(type.equals(QFieldType.INTEGER) || type.equals(QFieldType.DECIMAL) || type.equals(QFieldType.DATE) || type.equals(QFieldType.DATE_TIME) || type.equals(QFieldType.BOOLEAN))
|
||||||
@ -513,9 +515,9 @@ public abstract class AbstractRDBMSAction implements QActionInterface
|
|||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
**
|
**
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
protected Serializable getFieldValueFromResultSet(QFieldMetaData qFieldMetaData, ResultSet resultSet, int i) throws SQLException
|
protected Serializable getFieldValueFromResultSet(QFieldType type, ResultSet resultSet, int i) throws SQLException
|
||||||
{
|
{
|
||||||
switch(qFieldMetaData.getType())
|
switch(type)
|
||||||
{
|
{
|
||||||
case STRING:
|
case STRING:
|
||||||
case TEXT:
|
case TEXT:
|
||||||
@ -551,10 +553,19 @@ public abstract class AbstractRDBMSAction implements QActionInterface
|
|||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
throw new IllegalStateException("Unexpected field type: " + qFieldMetaData.getType());
|
throw new IllegalStateException("Unexpected field type: " + type);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
protected Serializable getFieldValueFromResultSet(QFieldMetaData qFieldMetaData, ResultSet resultSet, int i) throws SQLException
|
||||||
|
{
|
||||||
|
return (getFieldValueFromResultSet(qFieldMetaData.getType(), resultSet, i));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -575,6 +586,10 @@ public abstract class AbstractRDBMSAction implements QActionInterface
|
|||||||
String clause = (aggregate.getOperator() + "(" + escapeIdentifier(getColumnName(table.getField(aggregate.getFieldName()))) + ")");
|
String clause = (aggregate.getOperator() + "(" + escapeIdentifier(getColumnName(table.getField(aggregate.getFieldName()))) + ")");
|
||||||
clauses.add(clause + " " + ascOrDesc);
|
clauses.add(clause + " " + ascOrDesc);
|
||||||
}
|
}
|
||||||
|
else if(orderBy instanceof QFilterOrderByGroupBy orderByGroupBy)
|
||||||
|
{
|
||||||
|
clauses.add(getSingleGroupByClause(orderByGroupBy.getGroupBy(), joinsContext) + " " + ascOrDesc);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
JoinsContext.FieldAndTableNameOrAlias otherFieldAndTableNameOrAlias = joinsContext.getFieldAndTableNameOrAlias(orderBy.getFieldName());
|
JoinsContext.FieldAndTableNameOrAlias otherFieldAndTableNameOrAlias = joinsContext.getFieldAndTableNameOrAlias(orderBy.getFieldName());
|
||||||
@ -586,4 +601,23 @@ public abstract class AbstractRDBMSAction implements QActionInterface
|
|||||||
}
|
}
|
||||||
return (String.join(", ", clauses));
|
return (String.join(", ", clauses));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
protected String getSingleGroupByClause(GroupBy groupBy, JoinsContext joinsContext)
|
||||||
|
{
|
||||||
|
JoinsContext.FieldAndTableNameOrAlias fieldAndTableNameOrAlias = joinsContext.getFieldAndTableNameOrAlias(groupBy.getFieldName());
|
||||||
|
String fullFieldName = escapeIdentifier(fieldAndTableNameOrAlias.tableNameOrAlias()) + "." + escapeIdentifier(getColumnName(fieldAndTableNameOrAlias.field()));
|
||||||
|
if(groupBy.getFormatString() == null)
|
||||||
|
{
|
||||||
|
return (fullFieldName);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return (String.format(groupBy.getFormatString(), fullFieldName));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -34,6 +34,7 @@ import com.kingsrook.qqq.backend.core.model.actions.tables.aggregate.AggregateIn
|
|||||||
import com.kingsrook.qqq.backend.core.model.actions.tables.aggregate.AggregateOperator;
|
import com.kingsrook.qqq.backend.core.model.actions.tables.aggregate.AggregateOperator;
|
||||||
import com.kingsrook.qqq.backend.core.model.actions.tables.aggregate.AggregateOutput;
|
import com.kingsrook.qqq.backend.core.model.actions.tables.aggregate.AggregateOutput;
|
||||||
import com.kingsrook.qqq.backend.core.model.actions.tables.aggregate.AggregateResult;
|
import com.kingsrook.qqq.backend.core.model.actions.tables.aggregate.AggregateResult;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.actions.tables.aggregate.GroupBy;
|
||||||
import com.kingsrook.qqq.backend.core.model.actions.tables.query.JoinsContext;
|
import com.kingsrook.qqq.backend.core.model.actions.tables.query.JoinsContext;
|
||||||
import com.kingsrook.qqq.backend.core.model.actions.tables.query.QQueryFilter;
|
import com.kingsrook.qqq.backend.core.model.actions.tables.query.QQueryFilter;
|
||||||
import com.kingsrook.qqq.backend.core.model.metadata.fields.QFieldMetaData;
|
import com.kingsrook.qqq.backend.core.model.metadata.fields.QFieldMetaData;
|
||||||
@ -78,7 +79,7 @@ public class RDBMSAggregateAction extends AbstractRDBMSAction implements Aggrega
|
|||||||
sql += " WHERE " + makeWhereClause(aggregateInput.getInstance(), table, joinsContext, filter, params);
|
sql += " WHERE " + makeWhereClause(aggregateInput.getInstance(), table, joinsContext, filter, params);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(CollectionUtils.nullSafeHasContents(aggregateInput.getGroupByFieldNames()))
|
if(CollectionUtils.nullSafeHasContents(aggregateInput.getGroupBys()))
|
||||||
{
|
{
|
||||||
sql += " GROUP BY " + makeGroupByClause(aggregateInput, joinsContext);
|
sql += " GROUP BY " + makeGroupByClause(aggregateInput, joinsContext);
|
||||||
}
|
}
|
||||||
@ -105,11 +106,10 @@ public class RDBMSAggregateAction extends AbstractRDBMSAction implements Aggrega
|
|||||||
results.add(result);
|
results.add(result);
|
||||||
|
|
||||||
int selectionIndex = 1;
|
int selectionIndex = 1;
|
||||||
for(String groupByFieldName : CollectionUtils.nonNullList(aggregateInput.getGroupByFieldNames()))
|
for(GroupBy groupBy : CollectionUtils.nonNullList(aggregateInput.getGroupBys()))
|
||||||
{
|
{
|
||||||
JoinsContext.FieldAndTableNameOrAlias fieldAndTableNameOrAlias = joinsContext.getFieldAndTableNameOrAlias(groupByFieldName);
|
Serializable value = getFieldValueFromResultSet(groupBy.getType(), resultSet, selectionIndex++);
|
||||||
Serializable value = getFieldValueFromResultSet(fieldAndTableNameOrAlias.field(), resultSet, selectionIndex++);
|
result.withGroupByValue(groupBy, value);
|
||||||
result.withGroupByValue(groupByFieldName, value);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for(Aggregate aggregate : aggregateInput.getAggregates())
|
for(Aggregate aggregate : aggregateInput.getAggregates())
|
||||||
@ -148,10 +148,9 @@ public class RDBMSAggregateAction extends AbstractRDBMSAction implements Aggrega
|
|||||||
{
|
{
|
||||||
List<String> rs = new ArrayList<>();
|
List<String> rs = new ArrayList<>();
|
||||||
|
|
||||||
for(String groupByFieldName : CollectionUtils.nonNullList(aggregateInput.getGroupByFieldNames()))
|
for(GroupBy groupBy : CollectionUtils.nonNullList(aggregateInput.getGroupBys()))
|
||||||
{
|
{
|
||||||
JoinsContext.FieldAndTableNameOrAlias fieldAndTableNameOrAlias = joinsContext.getFieldAndTableNameOrAlias(groupByFieldName);
|
rs.add(getSingleGroupByClause(groupBy, joinsContext));
|
||||||
rs.add(escapeIdentifier(fieldAndTableNameOrAlias.tableNameOrAlias()) + "." + escapeIdentifier(getColumnName(fieldAndTableNameOrAlias.field())));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for(Aggregate aggregate : aggregateInput.getAggregates())
|
for(Aggregate aggregate : aggregateInput.getAggregates())
|
||||||
@ -170,10 +169,9 @@ public class RDBMSAggregateAction extends AbstractRDBMSAction implements Aggrega
|
|||||||
private String makeGroupByClause(AggregateInput aggregateInput, JoinsContext joinsContext)
|
private String makeGroupByClause(AggregateInput aggregateInput, JoinsContext joinsContext)
|
||||||
{
|
{
|
||||||
List<String> columns = new ArrayList<>();
|
List<String> columns = new ArrayList<>();
|
||||||
for(String groupByFieldName : aggregateInput.getGroupByFieldNames())
|
for(GroupBy groupBy : CollectionUtils.nonNullList(aggregateInput.getGroupBys()))
|
||||||
{
|
{
|
||||||
JoinsContext.FieldAndTableNameOrAlias fieldAndTableNameOrAlias = joinsContext.getFieldAndTableNameOrAlias(groupByFieldName);
|
columns.add(getSingleGroupByClause(groupBy, joinsContext));
|
||||||
columns.add(escapeIdentifier(fieldAndTableNameOrAlias.tableNameOrAlias()) + "." + escapeIdentifier(getColumnName(fieldAndTableNameOrAlias.field())));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return (StringUtils.join(",", columns));
|
return (StringUtils.join(",", columns));
|
||||||
|
@ -32,6 +32,7 @@ import com.kingsrook.qqq.backend.core.model.actions.tables.aggregate.AggregateIn
|
|||||||
import com.kingsrook.qqq.backend.core.model.actions.tables.aggregate.AggregateOperator;
|
import com.kingsrook.qqq.backend.core.model.actions.tables.aggregate.AggregateOperator;
|
||||||
import com.kingsrook.qqq.backend.core.model.actions.tables.aggregate.AggregateOutput;
|
import com.kingsrook.qqq.backend.core.model.actions.tables.aggregate.AggregateOutput;
|
||||||
import com.kingsrook.qqq.backend.core.model.actions.tables.aggregate.AggregateResult;
|
import com.kingsrook.qqq.backend.core.model.actions.tables.aggregate.AggregateResult;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.actions.tables.aggregate.GroupBy;
|
||||||
import com.kingsrook.qqq.backend.core.model.actions.tables.aggregate.QFilterOrderByAggregate;
|
import com.kingsrook.qqq.backend.core.model.actions.tables.aggregate.QFilterOrderByAggregate;
|
||||||
import com.kingsrook.qqq.backend.core.model.actions.tables.insert.InsertInput;
|
import com.kingsrook.qqq.backend.core.model.actions.tables.insert.InsertInput;
|
||||||
import com.kingsrook.qqq.backend.core.model.actions.tables.query.QCriteriaOperator;
|
import com.kingsrook.qqq.backend.core.model.actions.tables.query.QCriteriaOperator;
|
||||||
@ -40,6 +41,7 @@ import com.kingsrook.qqq.backend.core.model.actions.tables.query.QFilterOrderBy;
|
|||||||
import com.kingsrook.qqq.backend.core.model.actions.tables.query.QQueryFilter;
|
import com.kingsrook.qqq.backend.core.model.actions.tables.query.QQueryFilter;
|
||||||
import com.kingsrook.qqq.backend.core.model.actions.tables.query.QueryJoin;
|
import com.kingsrook.qqq.backend.core.model.actions.tables.query.QueryJoin;
|
||||||
import com.kingsrook.qqq.backend.core.model.data.QRecord;
|
import com.kingsrook.qqq.backend.core.model.data.QRecord;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.metadata.fields.QFieldType;
|
||||||
import com.kingsrook.qqq.backend.core.model.session.QSession;
|
import com.kingsrook.qqq.backend.core.model.session.QSession;
|
||||||
import com.kingsrook.qqq.backend.module.rdbms.TestUtils;
|
import com.kingsrook.qqq.backend.module.rdbms.TestUtils;
|
||||||
import org.junit.jupiter.api.Assertions;
|
import org.junit.jupiter.api.Assertions;
|
||||||
@ -145,7 +147,7 @@ public class RDBMSAggregateActionTest extends RDBMSActionTest
|
|||||||
aggregateInput.withAggregate(countOfId);
|
aggregateInput.withAggregate(countOfId);
|
||||||
aggregateInput.withAggregate(sumOfDaysWorked);
|
aggregateInput.withAggregate(sumOfDaysWorked);
|
||||||
|
|
||||||
aggregateInput.withGroupByFieldName("lastName");
|
aggregateInput.withGroupBy(new GroupBy(QFieldType.STRING, "lastName", null));
|
||||||
aggregateInput.setFilter(new QQueryFilter().withOrderBy(new QFilterOrderBy("lastName")));
|
aggregateInput.setFilter(new QQueryFilter().withOrderBy(new QFilterOrderBy("lastName")));
|
||||||
|
|
||||||
AggregateOutput aggregateOutput = new RDBMSAggregateAction().execute(aggregateInput);
|
AggregateOutput aggregateOutput = new RDBMSAggregateAction().execute(aggregateInput);
|
||||||
@ -182,8 +184,8 @@ public class RDBMSAggregateActionTest extends RDBMSActionTest
|
|||||||
aggregateInput.withAggregate(countOfId);
|
aggregateInput.withAggregate(countOfId);
|
||||||
aggregateInput.withAggregate(sumOfDaysWorked);
|
aggregateInput.withAggregate(sumOfDaysWorked);
|
||||||
|
|
||||||
aggregateInput.withGroupByFieldName("lastName");
|
aggregateInput.withGroupBy(new GroupBy(QFieldType.STRING, "lastName", null));
|
||||||
aggregateInput.withGroupByFieldName("firstName");
|
aggregateInput.withGroupBy(new GroupBy(QFieldType.STRING, "firstName", null));
|
||||||
|
|
||||||
aggregateInput.setFilter(new QQueryFilter()
|
aggregateInput.setFilter(new QQueryFilter()
|
||||||
.withOrderBy(new QFilterOrderBy("lastName"))
|
.withOrderBy(new QFilterOrderBy("lastName"))
|
||||||
@ -238,7 +240,7 @@ public class RDBMSAggregateActionTest extends RDBMSActionTest
|
|||||||
aggregateInput.withAggregate(countOfId);
|
aggregateInput.withAggregate(countOfId);
|
||||||
// note - don't query this value - just order by it!! aggregateInput.withAggregate(sumOfDaysWorked);
|
// note - don't query this value - just order by it!! aggregateInput.withAggregate(sumOfDaysWorked);
|
||||||
|
|
||||||
aggregateInput.withGroupByFieldName("lastName");
|
aggregateInput.withGroupBy(new GroupBy(QFieldType.STRING, "lastName", null));
|
||||||
|
|
||||||
aggregateInput.setFilter(new QQueryFilter().withOrderBy(new QFilterOrderByAggregate(sumOfDaysWorked, false)));
|
aggregateInput.setFilter(new QQueryFilter().withOrderBy(new QFilterOrderByAggregate(sumOfDaysWorked, false)));
|
||||||
|
|
||||||
@ -290,7 +292,7 @@ public class RDBMSAggregateActionTest extends RDBMSActionTest
|
|||||||
/////////////////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// but re-run w/ a group-by -- then, if no rows are found, there are 0 result objects. //
|
// but re-run w/ a group-by -- then, if no rows are found, there are 0 result objects. //
|
||||||
/////////////////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////////////////
|
||||||
aggregateInput.withGroupByFieldName("lastName");
|
aggregateInput.withGroupBy(new GroupBy(QFieldType.STRING, "lastName", null));
|
||||||
aggregateOutput = new RDBMSAggregateAction().execute(aggregateInput);
|
aggregateOutput = new RDBMSAggregateAction().execute(aggregateInput);
|
||||||
assertTrue(aggregateOutput.getResults().isEmpty());
|
assertTrue(aggregateOutput.getResults().isEmpty());
|
||||||
}
|
}
|
||||||
@ -328,7 +330,7 @@ public class RDBMSAggregateActionTest extends RDBMSActionTest
|
|||||||
aggregateInput.setSession(new QSession());
|
aggregateInput.setSession(new QSession());
|
||||||
aggregateInput.setTableName(TestUtils.TABLE_NAME_ORDER);
|
aggregateInput.setTableName(TestUtils.TABLE_NAME_ORDER);
|
||||||
aggregateInput.withAggregate(sumOfQuantity);
|
aggregateInput.withAggregate(sumOfQuantity);
|
||||||
aggregateInput.withGroupByFieldName(TestUtils.TABLE_NAME_ORDER_LINE + ".sku");
|
aggregateInput.withGroupBy(new GroupBy(QFieldType.STRING, TestUtils.TABLE_NAME_ORDER_LINE + ".sku", null));
|
||||||
aggregateInput.withQueryJoin(new QueryJoin(TestUtils.TABLE_NAME_ORDER, TestUtils.TABLE_NAME_ORDER_LINE));
|
aggregateInput.withQueryJoin(new QueryJoin(TestUtils.TABLE_NAME_ORDER, TestUtils.TABLE_NAME_ORDER_LINE));
|
||||||
|
|
||||||
AggregateOutput aggregateOutput = new RDBMSAggregateAction().execute(aggregateInput);
|
AggregateOutput aggregateOutput = new RDBMSAggregateAction().execute(aggregateInput);
|
||||||
|
Reference in New Issue
Block a user