SearchKit - Allow aggregate functions to be used without GroupBy
authorcolemanw <coleman@civicrm.org>
Fri, 29 Dec 2023 03:19:52 +0000 (21:19 -0600)
committercolemanw <coleman@civicrm.org>
Fri, 29 Dec 2023 03:19:52 +0000 (21:19 -0600)
Fixes https://lab.civicrm.org/dev/core/-/issues/2415

ext/search_kit/ang/crmSearchAdmin/crmSearchAdmin.component.js

index 48e8f31f7bd9edd1dba2c816f50c757b7da651e4..79fb64869bf1e992abae1395d03cf65749656583 100644 (file)
       _.each(ctrl.savedSearch.api_params.select, function(col, pos) {
         var info = searchMeta.parseExpr(col),
           fieldExpr = (_.findWhere(info.args, {type: 'field'}) || {}).value;
-        if (ctrl.canAggregate(col)) {
+        if (ctrl.mustAggregate(col)) {
           // Ensure all non-grouped columns are aggregated if using GROUP BY
           if (!info.fn || info.fn.category !== 'aggregate') {
             var dflFn = searchMeta.getDefaultAggregateFn(info) || 'GROUP_CONCAT',
 
     // Is a column eligible to use an aggregate function?
     this.canAggregate = function(col) {
-      // If the query does not use grouping, never
+      // If the query does not use grouping, it's always allowed
+      if (!ctrl.savedSearch.api_params.groupBy || !ctrl.savedSearch.api_params.groupBy.length) {
+        return true;
+      }
+      return this.mustAggregate(col);
+    };
+
+    // Is a column required to use an aggregate function?
+    this.mustAggregate = function(col) {
+      // If the query does not use grouping, it's never required
       if (!ctrl.savedSearch.api_params.groupBy || !ctrl.savedSearch.api_params.groupBy.length) {
         return false;
       }
           if (info.field && !info.suffix && !info.fn && info.field.type === 'Field' && (info.field.fk_entity || info.field.name !== info.field.fieldName)) {
             var idFieldName = info.field.fk_entity ? fieldName : fieldName.substr(0, fieldName.lastIndexOf('.')),
               idField = searchMeta.parseExpr(idFieldName).args[0].field;
-            if (!ctrl.canAggregate(idFieldName)) {
+            if (!ctrl.mustAggregate(idFieldName)) {
               var joinEntity = searchMeta.getEntity(idField.fk_entity),
                 label = (idField.join ? idField.join.label + ': ' : '') + (idField.input_attrs && idField.input_attrs.label || idField.label);
               _.each(_.cloneDeep(joinEntity && joinEntity.links), function(link) {