mirror of
https://github.com/Kingsrook/qqq.git
synced 2025-07-18 13:10:44 +00:00
CE-881 - Update to convert pivots to summaries for formats that don't support pivot
This commit is contained in:
@ -67,7 +67,7 @@ public class RenderSavedReportExecuteStep implements BackendStep
|
||||
|
||||
runBackendStepInput.getAsyncJobCallback().updateStatus("Generating Report");
|
||||
|
||||
QReportMetaData reportMetaData = new SavedReportToReportMetaDataAdapter().adapt(savedReport);
|
||||
QReportMetaData reportMetaData = new SavedReportToReportMetaDataAdapter().adapt(savedReport, reportFormat);
|
||||
|
||||
try(FileOutputStream reportOutputStream = new FileOutputStream(tmpFile))
|
||||
{
|
||||
|
@ -29,8 +29,13 @@ import java.util.Set;
|
||||
import com.fasterxml.jackson.databind.DeserializationFeature;
|
||||
import com.kingsrook.qqq.backend.core.context.QContext;
|
||||
import com.kingsrook.qqq.backend.core.exceptions.QException;
|
||||
import com.kingsrook.qqq.backend.core.exceptions.QUserFacingException;
|
||||
import com.kingsrook.qqq.backend.core.logging.QLogger;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.reporting.ReportFormat;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.reporting.pivottable.PivotTableDefinition;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.reporting.pivottable.PivotTableGroupBy;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.reporting.pivottable.PivotTableValue;
|
||||
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.QueryJoin;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.QInstance;
|
||||
@ -48,7 +53,6 @@ import com.kingsrook.qqq.backend.core.model.savedreports.SavedReport;
|
||||
import com.kingsrook.qqq.backend.core.utils.CollectionUtils;
|
||||
import com.kingsrook.qqq.backend.core.utils.JsonUtils;
|
||||
import com.kingsrook.qqq.backend.core.utils.StringUtils;
|
||||
import com.kingsrook.qqq.backend.core.utils.ValueUtils;
|
||||
import com.kingsrook.qqq.backend.core.utils.collections.ListBuilder;
|
||||
import org.apache.commons.lang.BooleanUtils;
|
||||
import static com.kingsrook.qqq.backend.core.logging.LogUtils.logPair;
|
||||
@ -66,7 +70,7 @@ public class SavedReportToReportMetaDataAdapter
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
public QReportMetaData adapt(SavedReport savedReport) throws QException
|
||||
public QReportMetaData adapt(SavedReport savedReport, ReportFormat reportFormat) throws QException
|
||||
{
|
||||
try
|
||||
{
|
||||
@ -97,11 +101,11 @@ public class SavedReportToReportMetaDataAdapter
|
||||
view.setLabel(savedReport.getLabel()); // todo eh?
|
||||
view.setIncludeHeaderRow(true);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// columns in the saved-report should look like a serialized version of ReportColumns object //
|
||||
// map them to a list of QReportField objects //
|
||||
// also keep track of what joinTables we find that we need to select //
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// columns in the saved-report should look like a serialized version of ReportColumns object //
|
||||
// map them to a list of QReportField objects //
|
||||
// also keep track of what joinTables we find that we need to select //
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////
|
||||
ReportColumns columnsObject = JsonUtils.toObject(savedReport.getColumnsJson(), ReportColumns.class, om -> om.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES));
|
||||
|
||||
List<QReportField> reportColumns = new ArrayList<>();
|
||||
@ -122,9 +126,9 @@ public class SavedReportToReportMetaDataAdapter
|
||||
////////////////////////////////////////////////////
|
||||
// figure out the field being named by the column //
|
||||
////////////////////////////////////////////////////
|
||||
String fieldName = ValueUtils.getValueAsString(column.getName());
|
||||
QFieldMetaData field = getField(savedReport, fieldName, qInstance, neededJoinTables, table);
|
||||
if(field == null)
|
||||
String fieldName = column.getName();
|
||||
FieldAndJoinTable fieldAndJoinTable = getField(savedReport, fieldName, qInstance, neededJoinTables, table);
|
||||
if(fieldAndJoinTable == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
@ -132,16 +136,7 @@ public class SavedReportToReportMetaDataAdapter
|
||||
//////////////////////////////////////////////////
|
||||
// make a QReportField based on the table field //
|
||||
//////////////////////////////////////////////////
|
||||
QReportField reportField = new QReportField();
|
||||
reportColumns.add(reportField);
|
||||
|
||||
reportField.setName(fieldName);
|
||||
reportField.setLabel(field.getLabel());
|
||||
|
||||
if(StringUtils.hasContent(field.getPossibleValueSourceName()))
|
||||
{
|
||||
reportField.setShowPossibleValueLabel(true);
|
||||
}
|
||||
reportColumns.add(makeQReportField(fieldName, fieldAndJoinTable));
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
@ -178,17 +173,93 @@ public class SavedReportToReportMetaDataAdapter
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////
|
||||
// if it's a pivot report, add that view too //
|
||||
///////////////////////////////////////////////
|
||||
/////////////////////////////////////////
|
||||
// if it's a pivot report, handle that //
|
||||
/////////////////////////////////////////
|
||||
if(StringUtils.hasContent(savedReport.getPivotTableJson()))
|
||||
{
|
||||
PivotTableDefinition pivotTableDefinition = JsonUtils.toObject(savedReport.getPivotTableJson(), PivotTableDefinition.class);
|
||||
|
||||
QReportView pivotView = new QReportView();
|
||||
reportMetaData.getViews().add(pivotView);
|
||||
pivotView.setName("pivot");
|
||||
pivotView.setType(ReportType.PIVOT);
|
||||
pivotView.setPivotTableSourceViewName(view.getName());
|
||||
pivotView.setPivotTableDefinition(JsonUtils.toObject(savedReport.getPivotTableJson(), PivotTableDefinition.class));
|
||||
pivotView.setLabel("Pivot Table");
|
||||
|
||||
if(reportFormat != null && reportFormat.getSupportsNativePivotTables())
|
||||
{
|
||||
pivotView.setType(ReportType.PIVOT);
|
||||
pivotView.setPivotTableSourceViewName(view.getName());
|
||||
pivotView.setPivotTableDefinition(pivotTableDefinition);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(!CollectionUtils.nullSafeHasContents(pivotTableDefinition.getRows()))
|
||||
{
|
||||
throw (new QUserFacingException("To generate a pivot report in " + reportFormat + " format, it must have 1 or more Pivot Rows"));
|
||||
}
|
||||
|
||||
if(CollectionUtils.nullSafeHasContents(pivotTableDefinition.getColumns()))
|
||||
{
|
||||
throw (new QUserFacingException("To generate a pivot report in " + reportFormat + " format, it may not have any Pivot Columns"));
|
||||
}
|
||||
|
||||
///////////////////////
|
||||
// handle pivot rows //
|
||||
///////////////////////
|
||||
List<String> summaryFields = new ArrayList<>();
|
||||
List<QFilterOrderBy> summaryOrderByFields = new ArrayList<>();
|
||||
for(PivotTableGroupBy row : pivotTableDefinition.getRows())
|
||||
{
|
||||
String fieldName = row.getFieldName();
|
||||
FieldAndJoinTable fieldAndJoinTable = getField(savedReport, fieldName, qInstance, neededJoinTables, table);
|
||||
if(fieldAndJoinTable == null)
|
||||
{
|
||||
LOG.warn("The field for a Pivot Row wasn't found, when converting to a summary...", logPair("savedReportId", savedReport.getId()), logPair("fieldName", fieldName));
|
||||
continue;
|
||||
}
|
||||
summaryFields.add(fieldName);
|
||||
summaryOrderByFields.add(new QFilterOrderBy(fieldName));
|
||||
}
|
||||
|
||||
/////////////////////////
|
||||
// handle pivot values //
|
||||
/////////////////////////
|
||||
List<QReportField> summaryViewColumns = new ArrayList<>();
|
||||
for(PivotTableValue value : pivotTableDefinition.getValues())
|
||||
{
|
||||
String fieldName = value.getFieldName();
|
||||
FieldAndJoinTable fieldAndJoinTable = getField(savedReport, fieldName, qInstance, neededJoinTables, table);
|
||||
if(fieldAndJoinTable == null)
|
||||
{
|
||||
LOG.warn("The field for a Pivot Value wasn't found, when converting to a summary...", logPair("savedReportId", savedReport.getId()), logPair("fieldName", fieldName));
|
||||
continue;
|
||||
}
|
||||
|
||||
QReportField reportField = makeQReportField(fieldName, fieldAndJoinTable);
|
||||
reportField.setName(fieldName + "_" + value.getFunction().name());
|
||||
reportField.setLabel(StringUtils.ucFirst(value.getFunction().name().toLowerCase()) + " Of " + reportField.getLabel());
|
||||
reportField.setFormula("${pivot." + value.getFunction().name().toLowerCase() + "." + fieldName + "}");
|
||||
summaryViewColumns.add(reportField);
|
||||
summaryOrderByFields.add(new QFilterOrderBy(reportField.getName()));
|
||||
}
|
||||
|
||||
pivotView.setType(ReportType.SUMMARY);
|
||||
pivotView.setDataSourceName(dataSource.getName());
|
||||
pivotView.setIncludeHeaderRow(true);
|
||||
pivotView.setIncludeTotalRow(true);
|
||||
pivotView.setColumns(summaryViewColumns);
|
||||
pivotView.setSummaryFields(summaryFields);
|
||||
pivotView.withOrderByFields(summaryOrderByFields);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////
|
||||
// in case the reportFormat doesn't support multiple views, and we have a pivot - //
|
||||
// then remove the data view //
|
||||
////////////////////////////////////////////////////////////////////////////////////
|
||||
if(reportFormat != null && !reportFormat.getSupportsMultipleViews())
|
||||
{
|
||||
reportMetaData.getViews().remove(0);
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
@ -217,7 +288,44 @@ public class SavedReportToReportMetaDataAdapter
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
private static QFieldMetaData getField(SavedReport savedReport, String fieldName, QInstance qInstance, Set<String> neededJoinTables, QTableMetaData table)
|
||||
private static QReportField makeQReportField(String fieldName, FieldAndJoinTable fieldAndJoinTable)
|
||||
{
|
||||
QReportField reportField = new QReportField();
|
||||
|
||||
reportField.setName(fieldName);
|
||||
|
||||
if(fieldAndJoinTable.joinTable() == null)
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
// for fields from this table, just use the field's label //
|
||||
////////////////////////////////////////////////////////////
|
||||
reportField.setLabel(fieldAndJoinTable.field().getLabel());
|
||||
}
|
||||
else
|
||||
{
|
||||
///////////////////////////////////////////////////////////////
|
||||
// for fields from join tables, use table label: field label //
|
||||
///////////////////////////////////////////////////////////////
|
||||
reportField.setLabel(fieldAndJoinTable.joinTable().getLabel() + ": " + fieldAndJoinTable.field().getLabel());
|
||||
}
|
||||
|
||||
if(StringUtils.hasContent(fieldAndJoinTable.field().getPossibleValueSourceName()))
|
||||
{
|
||||
reportField.setShowPossibleValueLabel(true);
|
||||
}
|
||||
|
||||
reportField.setType(fieldAndJoinTable.field().getType());
|
||||
|
||||
return reportField;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
private static FieldAndJoinTable getField(SavedReport savedReport, String fieldName, QInstance qInstance, Set<String> neededJoinTables, QTableMetaData table)
|
||||
{
|
||||
QFieldMetaData field;
|
||||
if(fieldName.contains("."))
|
||||
@ -240,6 +348,8 @@ public class SavedReportToReportMetaDataAdapter
|
||||
LOG.warn("Saved Report has an unrecognized join field name", logPair("savedReportId", savedReport.getId()), logPair("fieldName", fieldName));
|
||||
return null;
|
||||
}
|
||||
|
||||
return new FieldAndJoinTable(field, joinTable);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -255,8 +365,15 @@ public class SavedReportToReportMetaDataAdapter
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
return new FieldAndJoinTable(field, null);
|
||||
}
|
||||
return field;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
private record FieldAndJoinTable(QFieldMetaData field, QTableMetaData joinTable) {}
|
||||
}
|
||||
|
Reference in New Issue
Block a user