diff --git a/packages/builder/src/components/backend/DataTable/buttons/grid/GridViewCalculationButton.svelte b/packages/builder/src/components/backend/DataTable/buttons/grid/GridViewCalculationButton.svelte index 7733a90bad..1e5ea1ebf6 100644 --- a/packages/builder/src/components/backend/DataTable/buttons/grid/GridViewCalculationButton.svelte +++ b/packages/builder/src/components/backend/DataTable/buttons/grid/GridViewCalculationButton.svelte @@ -6,7 +6,13 @@ Multiselect, Button, } from "@budibase/bbui" - import { CalculationType, canGroupBy, isNumeric } from "@budibase/types" + import { + CalculationType, + canGroupBy, + FieldType, + isNumeric, + isNumericStaticFormula, + } from "@budibase/types" import InfoDisplay from "@/pages/builder/app/[application]/design/[screenId]/[componentId]/_components/Component/InfoDisplay.svelte" import { getContext } from "svelte" import DetailPopover from "@/components/common/DetailPopover.svelte" @@ -94,10 +100,15 @@ if (fieldSchema.calculationType) { return false } + // static numeric formulas will work + if (isNumericStaticFormula(fieldSchema)) { + return true + } // Only allow numeric columns for most calculation types if ( self.type !== CalculationType.COUNT && - !isNumeric(fieldSchema.type) + !isNumeric(fieldSchema.type) && + fieldSchema.responseType !== FieldType.NUMBER ) { return false } diff --git a/packages/server/src/api/routes/tests/viewV2.spec.ts b/packages/server/src/api/routes/tests/viewV2.spec.ts index bca7d16807..261cd097d9 100644 --- a/packages/server/src/api/routes/tests/viewV2.spec.ts +++ b/packages/server/src/api/routes/tests/viewV2.spec.ts @@ -35,6 +35,7 @@ import { ViewV2, ViewV2Schema, ViewV2Type, + FormulaType, } from "@budibase/types" import { generator, mocks } from "@budibase/backend-core/tests" import { datasourceDescribe } from "../../../integrations/tests/utils" @@ -3865,6 +3866,48 @@ if (descriptions.length) { expect(rows[0].count).toEqual(2) }) + isInternal && + it("should be able to max a static formula field", async () => { + const table = await config.api.table.save( + saveTableRequest({ + schema: { + string: { + type: FieldType.STRING, + name: "string", + }, + formula: { + type: FieldType.FORMULA, + name: "formula", + formulaType: FormulaType.STATIC, + responseType: FieldType.NUMBER, + formula: "{{ string }}", + }, + }, + }) + ) + await config.api.row.save(table._id!, { + string: "1", + }) + await config.api.row.save(table._id!, { + string: "2", + }) + const view = await config.api.viewV2.create({ + tableId: table._id!, + name: generator.guid(), + type: ViewV2Type.CALCULATION, + schema: { + maxFormula: { + visible: true, + calculationType: CalculationType.MAX, + field: "formula", + }, + }, + }) + const { rows } = await config.api.row.search(view.id) + expect(rows.length).toEqual(1) + expect(rows[0].maxFormula).toEqual(2) + }) + it("should not be able to COUNT(DISTINCT ...) against a non-existent field", async () => { await config.api.viewV2.create( { diff --git a/packages/server/src/sdk/app/views/index.ts b/packages/server/src/sdk/app/views/index.ts index b3edc92e17..7f67e95e66 100644 --- a/packages/server/src/sdk/app/views/index.ts +++ b/packages/server/src/sdk/app/views/index.ts @@ -4,6 +4,7 @@ import { canGroupBy, FieldType, isNumeric, + isNumericStaticFormula, PermissionLevel, RelationSchemaField, RenameColumn, @@ -176,7 +177,11 @@ async function guardCalculationViewSchema( } const isCount = schema.calculationType === CalculationType.COUNT - if (!isCount && !isNumeric(targetSchema.type)) { + if ( + !isCount && + !isNumeric(targetSchema.type) && + !isNumericStaticFormula(targetSchema) + ) { throw new HTTPError( `Calculation field "${name}" references field "${schema.field}" which is not a numeric field`, 400 diff --git a/packages/types/src/documents/app/row.ts b/packages/types/src/documents/app/row.ts index 4c32e45a8c..e508c4e3c0 100644 --- a/packages/types/src/documents/app/row.ts +++ b/packages/types/src/documents/app/row.ts @@ -1,4 +1,5 @@ import { Document } from "../document" +import { FieldSchema, FormulaType } from "./table" export enum FieldType { /** @@ -147,6 +148,15 @@ export function isNumeric(type: FieldType) { return NumericTypes.includes(type) } +export function isNumericStaticFormula(schema: FieldSchema) { + return ( + schema.type === FieldType.FORMULA && + schema.formulaType === FormulaType.STATIC && + schema.responseType && + isNumeric(schema.responseType) + ) +} + export const GroupByTypes = [ FieldType.STRING, FieldType.LONGFORM,