From 71326885a9fc44048c34b40132323cc8af3f2e2e Mon Sep 17 00:00:00 2001 From: Stepan Houdek Date: Thu, 4 Jun 2026 15:53:40 +0200 Subject: [PATCH 1/8] Add: formula field support --- .../.template.config/template.json | 11 +++++++++++ .../pp-entity-attribute/.template.temp/attribute.xml | 7 +++++++ .../Formulas/__attribute-schema-name__.yaml | 0 3 files changed, 18 insertions(+) create mode 100644 src/Dataverse/templates/pp-entity-attribute/__solution-root-path__/Entities/__entity-schema-name__/Formulas/__attribute-schema-name__.yaml diff --git a/src/Dataverse/templates/pp-entity-attribute/.template.config/template.json b/src/Dataverse/templates/pp-entity-attribute/.template.config/template.json index 3d0fd83e..ce69c952 100644 --- a/src/Dataverse/templates/pp-entity-attribute/.template.config/template.json +++ b/src/Dataverse/templates/pp-entity-attribute/.template.config/template.json @@ -18,6 +18,10 @@ { "condition": "(!CreateGlobalOptionSet)", "exclude": ["__solution-root-path__/OptionSets/*"] + }, + { + "condition": "(!IsFormulaField)", + "exclude": ["__solution-root-path__/Entities/__entity-schema-name__/Formulas/__attribute-schema-name__.yaml"] } ] } @@ -149,6 +153,13 @@ { "choice": "3", "description": "Time zone independent (stores actual value)" } ] }, + "IsFormulaField": { + "type": "parameter", + "description": "[Text/Decimal/WholeNumber/Float/Boolean/Choice/DateTime] Set true to mark this column as a formula field. This sets SourceType to 3 and adds FormulaDefinitionFileName metadata.", + "datatype": "bool", + "defaultValue": false, + "isEnabled": "(AttributeType == \"Text\" || AttributeType == \"Decimal\" || AttributeType == \"WholeNumber\" || AttributeType == \"Float\" || AttributeType == \"Boolean\" || AttributeType == \"OptionSet(Local)\" || AttributeType == \"OptionSet(Global)\" || AttributeType == \"DateTime\")" + }, "BooleanTrueLabel": { "type": "parameter", "description": "[Boolean] Label for the true/yes option.", diff --git a/src/Dataverse/templates/pp-entity-attribute/.template.temp/attribute.xml b/src/Dataverse/templates/pp-entity-attribute/.template.temp/attribute.xml index b059ff77..947a3b8d 100644 --- a/src/Dataverse/templates/pp-entity-attribute/.template.temp/attribute.xml +++ b/src/Dataverse/templates/pp-entity-attribute/.template.temp/attribute.xml @@ -81,7 +81,11 @@ 1 1 + + 3 + 0 + 1 @@ -215,4 +219,7 @@ + + /Formulas/__attribute-schema-name__.yaml + diff --git a/src/Dataverse/templates/pp-entity-attribute/__solution-root-path__/Entities/__entity-schema-name__/Formulas/__attribute-schema-name__.yaml b/src/Dataverse/templates/pp-entity-attribute/__solution-root-path__/Entities/__entity-schema-name__/Formulas/__attribute-schema-name__.yaml new file mode 100644 index 00000000..e69de29b From 8b19d581d6fc2e5a52dc722a616d71c8a81d6947 Mon Sep 17 00:00:00 2001 From: Stepan Houdek Date: Fri, 5 Jun 2026 16:38:10 +0200 Subject: [PATCH 2/8] Update: change condition from IsFormulaField to IsFormulaFieldComputed in template files --- .../pp-entity-attribute/.template.config/template.json | 8 ++++++-- .../pp-entity-attribute/.template.temp/attribute.xml | 4 ++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/Dataverse/templates/pp-entity-attribute/.template.config/template.json b/src/Dataverse/templates/pp-entity-attribute/.template.config/template.json index ce69c952..adbb9b82 100644 --- a/src/Dataverse/templates/pp-entity-attribute/.template.config/template.json +++ b/src/Dataverse/templates/pp-entity-attribute/.template.config/template.json @@ -20,7 +20,7 @@ "exclude": ["__solution-root-path__/OptionSets/*"] }, { - "condition": "(!IsFormulaField)", + "condition": "(!IsFormulaFieldComputed)", "exclude": ["__solution-root-path__/Entities/__entity-schema-name__/Formulas/__attribute-schema-name__.yaml"] } ] @@ -157,9 +157,13 @@ "type": "parameter", "description": "[Text/Decimal/WholeNumber/Float/Boolean/Choice/DateTime] Set true to mark this column as a formula field. This sets SourceType to 3 and adds FormulaDefinitionFileName metadata.", "datatype": "bool", - "defaultValue": false, + "defaultValue": "false", "isEnabled": "(AttributeType == \"Text\" || AttributeType == \"Decimal\" || AttributeType == \"WholeNumber\" || AttributeType == \"Float\" || AttributeType == \"Boolean\" || AttributeType == \"OptionSet(Local)\" || AttributeType == \"OptionSet(Global)\" || AttributeType == \"DateTime\")" }, + "IsFormulaFieldComputed": { + "type": "computed", + "value": "(IsFormulaField)" + }, "BooleanTrueLabel": { "type": "parameter", "description": "[Boolean] Label for the true/yes option.", diff --git a/src/Dataverse/templates/pp-entity-attribute/.template.temp/attribute.xml b/src/Dataverse/templates/pp-entity-attribute/.template.temp/attribute.xml index 947a3b8d..5cea8ada 100644 --- a/src/Dataverse/templates/pp-entity-attribute/.template.temp/attribute.xml +++ b/src/Dataverse/templates/pp-entity-attribute/.template.temp/attribute.xml @@ -81,7 +81,7 @@ 1 1 - + 3 0 @@ -219,7 +219,7 @@ - + /Formulas/__attribute-schema-name__.yaml From 055cc69760dea4990c3972d3817a8aa7951eab5e Mon Sep 17 00:00:00 2001 From: Stepan Houdek Date: Fri, 5 Jun 2026 16:46:52 +0200 Subject: [PATCH 3/8] Update: enhance IsFormulaField description to include YAML file generation and formula expression guidelines --- .../pp-entity-attribute/.template.config/template.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Dataverse/templates/pp-entity-attribute/.template.config/template.json b/src/Dataverse/templates/pp-entity-attribute/.template.config/template.json index adbb9b82..68b25c73 100644 --- a/src/Dataverse/templates/pp-entity-attribute/.template.config/template.json +++ b/src/Dataverse/templates/pp-entity-attribute/.template.config/template.json @@ -155,7 +155,7 @@ }, "IsFormulaField": { "type": "parameter", - "description": "[Text/Decimal/WholeNumber/Float/Boolean/Choice/DateTime] Set true to mark this column as a formula field. This sets SourceType to 3 and adds FormulaDefinitionFileName metadata.", + "description": "[Text/Decimal/WholeNumber/Float/Boolean/Choice/DateTime] Set true to mark this column as a formula field. This sets SourceType to 3, adds FormulaDefinitionFileName metadata pointing to Entities/{EntitySchemaName}/Formulas/{AttributeSchemaName}.yaml, and generates that YAML file as a placeholder. After scaffolding, populate the YAML file with the Power Fx formula expression under the 'prefix + logical name' key (e.g., 'uddp_formulafield: =ThisRecord.udpp_price * ThisRecord.udpp_quantity'). For multi-line formulas use |- (e.g. 'uddp_formulafield: |- =ThisRecord.udpp_price * ThisRecord.udpp_quantity'). Reference same-record columns via ThisRecord.column_logical_name. The formula's return type must match the chosen AttributeType (e.g., a Decimal formula for a Decimal column). Supported operators: +, -, *, /, %, in, exactin, &. Use Power Fx functions such as If, Switch, Concatenate, Text, DateAdd, UTCNow, etc.", "datatype": "bool", "defaultValue": "false", "isEnabled": "(AttributeType == \"Text\" || AttributeType == \"Decimal\" || AttributeType == \"WholeNumber\" || AttributeType == \"Float\" || AttributeType == \"Boolean\" || AttributeType == \"OptionSet(Local)\" || AttributeType == \"OptionSet(Global)\" || AttributeType == \"DateTime\")" From bfe99ee16b9aae4ac736ab148298280850833975 Mon Sep 17 00:00:00 2001 From: Stepan Houdek Date: Mon, 8 Jun 2026 09:53:21 +0200 Subject: [PATCH 4/8] Update: modify IsFormulaField description to include valid conditions and YAML file handling; add post-action for initializing formula definition YAML. --- .../.template.config/template.json | 21 +++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/src/Dataverse/templates/pp-entity-attribute/.template.config/template.json b/src/Dataverse/templates/pp-entity-attribute/.template.config/template.json index 68b25c73..fbdc8926 100644 --- a/src/Dataverse/templates/pp-entity-attribute/.template.config/template.json +++ b/src/Dataverse/templates/pp-entity-attribute/.template.config/template.json @@ -20,9 +20,8 @@ "exclude": ["__solution-root-path__/OptionSets/*"] }, { - "condition": "(!IsFormulaFieldComputed)", - "exclude": ["__solution-root-path__/Entities/__entity-schema-name__/Formulas/__attribute-schema-name__.yaml"] - } + "exclude": ["__solution-root-path__/Entities/__entity-schema-name__/Formulas/__entity-schema-name__-FormulaDefinitions.yaml"] + } ] } ], @@ -155,7 +154,7 @@ }, "IsFormulaField": { "type": "parameter", - "description": "[Text/Decimal/WholeNumber/Float/Boolean/Choice/DateTime] Set true to mark this column as a formula field. This sets SourceType to 3, adds FormulaDefinitionFileName metadata pointing to Entities/{EntitySchemaName}/Formulas/{AttributeSchemaName}.yaml, and generates that YAML file as a placeholder. After scaffolding, populate the YAML file with the Power Fx formula expression under the 'prefix + logical name' key (e.g., 'uddp_formulafield: =ThisRecord.udpp_price * ThisRecord.udpp_quantity'). For multi-line formulas use |- (e.g. 'uddp_formulafield: |- =ThisRecord.udpp_price * ThisRecord.udpp_quantity'). Reference same-record columns via ThisRecord.column_logical_name. The formula's return type must match the chosen AttributeType (e.g., a Decimal formula for a Decimal column). Supported operators: +, -, *, /, %, in, exactin, &. Use Power Fx functions such as If, Switch, Concatenate, Text, DateAdd, UTCNow, etc.", + "description": "[Text/Decimal/WholeNumber/Float/Boolean/Choice/DateTime] Set true to mark this column as a formula field. This sets SourceType to 3, sets ValidForCreate/UpdateApi to 0 (read-only), adds FormulaDefinitionFileName metadata pointing to Entities/{EntitySchemaName}/Formulas/{EntitySchemaName}-FormulaDefinitions.yaml, and creates or appends to that consolidated YAML file with a placeholder entry. After scaffolding, fill in the Power Fx expression after the colon (e.g., 'ntg_totalamount: =ThisRecord.ntg_price * ThisRecord.ntg_quantity'). For multi-line formulas use '|-'. Reference same-record columns via ThisRecord.column_logical_name. The formula's return type must match the chosen AttributeType. Supported operators: +, -, *, /, %, in, exactin, &. Use Power Fx functions such as If, Switch, Concatenate, Text, DateAdd, UTCNow, etc.", "datatype": "bool", "defaultValue": "false", "isEnabled": "(AttributeType == \"Text\" || AttributeType == \"Decimal\" || AttributeType == \"WholeNumber\" || AttributeType == \"Float\" || AttributeType == \"Boolean\" || AttributeType == \"OptionSet(Local)\" || AttributeType == \"OptionSet(Global)\" || AttributeType == \"DateTime\")" @@ -474,6 +473,20 @@ "description": "Adding lookup relationship xml" }, + { + "actionId": "3A7C4B45-1F5D-4A30-959A-51B88E82B5D2", + "condition": "(IsFormulaFieldComputed)", + "args": { + "executable": "pwsh", + "args": "-noprofile -executionpolicy bypass -File \"./.template.scripts/InitFormulaDefinition.ps1\"", + "redirectStandardOutput": "false" + }, + "manualInstructions": [ + { "text": "Initializing formula definition YAML" } + ], + "continueOnError": false, + "description": "Initializing formula definition YAML" + }, { "actionId": "3A7C4B45-1F5D-4A30-959A-51B88E82B5D2", "args": { From 02f8bb9455bd931000c0cb65f1949474e97be2d5 Mon Sep 17 00:00:00 2001 From: Stepan Houdek Date: Mon, 8 Jun 2026 09:53:29 +0200 Subject: [PATCH 5/8] Add: script to initialize formula definition YAML with placeholder entries --- .../InitFormulaDefinition.ps1 | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 src/Dataverse/templates/pp-entity-attribute/.template.scripts/InitFormulaDefinition.ps1 diff --git a/src/Dataverse/templates/pp-entity-attribute/.template.scripts/InitFormulaDefinition.ps1 b/src/Dataverse/templates/pp-entity-attribute/.template.scripts/InitFormulaDefinition.ps1 new file mode 100644 index 00000000..d2a7c2f8 --- /dev/null +++ b/src/Dataverse/templates/pp-entity-attribute/.template.scripts/InitFormulaDefinition.ps1 @@ -0,0 +1,27 @@ +$ErrorActionPreference = 'Stop' + +$formulasDir = (Resolve-Path '__solution-root-path__/Entities/__entity-schema-name__/Formulas' -ErrorAction SilentlyContinue)?.Path +$yamlPath = Join-Path ($formulasDir ?? (Join-Path '__solution-root-path__' 'Entities' '__entity-schema-name__' 'Formulas')) '__entity-schema-name__-FormulaDefinitions.yaml' +$entryKey = '__attribute-schema-name__:' + +# Create directory if it doesn't exist +if (-not (Test-Path (Split-Path $yamlPath))) { + New-Item -ItemType Directory -Path (Split-Path $yamlPath) -Force | Out-Null +} + +if (Test-Path $yamlPath) { + # File exists — check if this attribute's entry is already present + $content = Get-Content $yamlPath -Raw + $escapedKey = [regex]::Escape($entryKey) + if ($content -notmatch "(^|`n)$escapedKey") { + # Append new placeholder entry for the user to fill in + Add-Content -Path $yamlPath -Value "${entryKey} " + Write-Host "Appended formula placeholder for '$entryKey' in '$yamlPath'. Fill in the Power Fx expression after the colon." + } else { + Write-Host "Formula entry for '$entryKey' already exists in '$yamlPath'. Skipping." + } +} else { + # File doesn't exist — create it with the first placeholder entry + Set-Content -Path $yamlPath -Value "${entryKey} " + Write-Host "Created '$yamlPath' with formula placeholder for '$entryKey'. Fill in the Power Fx expression after the colon." +} From b99d9820242d3cc1a94c87d1d33173b510dff6e0 Mon Sep 17 00:00:00 2001 From: Stepan Houdek Date: Mon, 8 Jun 2026 09:53:45 +0200 Subject: [PATCH 6/8] Update: modify conditions for ValidForUpdateApi and ValidForCreateApi based on IsFormulaFieldComputed; change FormulaDefinitionFileName format. --- .../pp-entity-attribute/.template.temp/attribute.xml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Dataverse/templates/pp-entity-attribute/.template.temp/attribute.xml b/src/Dataverse/templates/pp-entity-attribute/.template.temp/attribute.xml index 5cea8ada..ecd43364 100644 --- a/src/Dataverse/templates/pp-entity-attribute/.template.temp/attribute.xml +++ b/src/Dataverse/templates/pp-entity-attribute/.template.temp/attribute.xml @@ -53,13 +53,13 @@ auto - + 0 1 1 - + 0 1 @@ -220,6 +220,6 @@ - /Formulas/__attribute-schema-name__.yaml + /Formulas/__entity-schema-name__-FormulaDefinitions.yaml From d791ab0d9f3843cdfdadf760aa892c8d341ac700 Mon Sep 17 00:00:00 2001 From: Stepan Houdek Date: Mon, 8 Jun 2026 09:53:57 +0200 Subject: [PATCH 7/8] Remove: delete empty formula YAML file for __attribute-schema-name__ and add new formula definitions file. --- .../Formulas/__attribute-schema-name__.yaml | 0 .../Formulas/__entity-schema-name__-FormulaDefinitions.yaml | 1 + 2 files changed, 1 insertion(+) delete mode 100644 src/Dataverse/templates/pp-entity-attribute/__solution-root-path__/Entities/__entity-schema-name__/Formulas/__attribute-schema-name__.yaml create mode 100644 src/Dataverse/templates/pp-entity-attribute/__solution-root-path__/Entities/__entity-schema-name__/Formulas/__entity-schema-name__-FormulaDefinitions.yaml diff --git a/src/Dataverse/templates/pp-entity-attribute/__solution-root-path__/Entities/__entity-schema-name__/Formulas/__attribute-schema-name__.yaml b/src/Dataverse/templates/pp-entity-attribute/__solution-root-path__/Entities/__entity-schema-name__/Formulas/__attribute-schema-name__.yaml deleted file mode 100644 index e69de29b..00000000 diff --git a/src/Dataverse/templates/pp-entity-attribute/__solution-root-path__/Entities/__entity-schema-name__/Formulas/__entity-schema-name__-FormulaDefinitions.yaml b/src/Dataverse/templates/pp-entity-attribute/__solution-root-path__/Entities/__entity-schema-name__/Formulas/__entity-schema-name__-FormulaDefinitions.yaml new file mode 100644 index 00000000..4487e0e7 --- /dev/null +++ b/src/Dataverse/templates/pp-entity-attribute/__solution-root-path__/Entities/__entity-schema-name__/Formulas/__entity-schema-name__-FormulaDefinitions.yaml @@ -0,0 +1 @@ +__attribute-schema-name__: From 3cb42b6e2d51239945ac26059cd37128f49377ca Mon Sep 17 00:00:00 2001 From: Stepan Houdek Date: Tue, 23 Jun 2026 11:29:50 +0200 Subject: [PATCH 8/8] Remove: useless computed field --- .../pp-entity-attribute/.template.config/template.json | 6 +----- .../pp-entity-attribute/.template.temp/attribute.xml | 8 ++++---- 2 files changed, 5 insertions(+), 9 deletions(-) diff --git a/src/Dataverse/templates/pp-entity-attribute/.template.config/template.json b/src/Dataverse/templates/pp-entity-attribute/.template.config/template.json index fbdc8926..228e0ecf 100644 --- a/src/Dataverse/templates/pp-entity-attribute/.template.config/template.json +++ b/src/Dataverse/templates/pp-entity-attribute/.template.config/template.json @@ -159,10 +159,6 @@ "defaultValue": "false", "isEnabled": "(AttributeType == \"Text\" || AttributeType == \"Decimal\" || AttributeType == \"WholeNumber\" || AttributeType == \"Float\" || AttributeType == \"Boolean\" || AttributeType == \"OptionSet(Local)\" || AttributeType == \"OptionSet(Global)\" || AttributeType == \"DateTime\")" }, - "IsFormulaFieldComputed": { - "type": "computed", - "value": "(IsFormulaField)" - }, "BooleanTrueLabel": { "type": "parameter", "description": "[Boolean] Label for the true/yes option.", @@ -475,7 +471,7 @@ { "actionId": "3A7C4B45-1F5D-4A30-959A-51B88E82B5D2", - "condition": "(IsFormulaFieldComputed)", + "condition": "(IsFormulaField)", "args": { "executable": "pwsh", "args": "-noprofile -executionpolicy bypass -File \"./.template.scripts/InitFormulaDefinition.ps1\"", diff --git a/src/Dataverse/templates/pp-entity-attribute/.template.temp/attribute.xml b/src/Dataverse/templates/pp-entity-attribute/.template.temp/attribute.xml index ecd43364..8fa5e1d0 100644 --- a/src/Dataverse/templates/pp-entity-attribute/.template.temp/attribute.xml +++ b/src/Dataverse/templates/pp-entity-attribute/.template.temp/attribute.xml @@ -53,13 +53,13 @@ auto - + 0 1 1 - + 0 1 @@ -81,7 +81,7 @@ 1 1 - + 3 0 @@ -219,7 +219,7 @@ - + /Formulas/__entity-schema-name__-FormulaDefinitions.yaml