Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -82,4 +82,9 @@ public sealed record CreateAttributeOptions
public bool IsAuditable { get; init; }
public bool IsSearchable { get; init; } = true;
public bool IsSecured { get; init; }

// === Formula ===

/// <summary>Power Fx formula expression. When set, SourceType is set to 3 (Formula). Supported base types: string, number, decimal, float, money, bool, datetime, choice, multichoice.</summary>
public string? FormulaDefinition { get; init; }
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ public static class AttributeTypeRegistry
public static IReadOnlyList<string> SharedParameterNames { get; } = new[]
{
"entity", "name", "display-name", "description", "required", "solution",
"is-auditable", "is-searchable", "is-secured"
"is-auditable", "is-searchable", "is-secured", "formula-definition"
};

private static ReadOnlyCollection<AttributeTypeInfo> BuildAllTypes()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ public class EntityAttributeCreateCliCommand : StagedCliCommand
[CliOption(Name = "--name", Description = "Schema name for the new column.", Required = true)]
public string Name { get; set; } = null!;

[CliOption(Name = "--type", Description = "Column type: string, memo, number, decimal, float, money, bool, datetime, choice, multichoice, lookup, polymorphic-lookup, customer, image, file, bigint.", Required = true)]
[CliOption(Name = "--type", Description = "Column type: string, memo, number, decimal, float, money, bool, datetime, choice, multichoice, lookup, polymorphic-lookup, customer, image, file, bigint. Add --formula-definition to make any supported type a formula column.", Required = true)]
public AttributeTypeArg Type { get; set; }

// === Optional for all types ===
Expand Down Expand Up @@ -134,6 +134,11 @@ public class EntityAttributeCreateCliCommand : StagedCliCommand
[DefaultValue(true)]
public bool CanStoreFullImage { get; set; } = true;

// === Formula ===

[CliOption(Name = "--formula-definition", Description = "Power Fx formula expression. When provided, creates the column as a formula field (SourceType=3). Supported types: string, number, decimal, float, money, bool, datetime, choice, multichoice.", Required = false)]
public string? FormulaDefinition { get; set; }

protected override async Task<int> ExecuteAsync()
{
ValidateExecutionMode();
Expand Down Expand Up @@ -177,6 +182,7 @@ protected override async Task<int> ExecuteAsync()
["cascadeDelete"] = options.CascadeDelete,
["maxSizeKb"] = options.MaxSizeKb,
["canStoreFullImage"] = options.CanStoreFullImage,
["formulaDefinition"] = options.FormulaDefinition,
["isAuditable"] = options.IsAuditable,
["isSearchable"] = options.IsSearchable,
["isSecured"] = options.IsSecured
Expand Down Expand Up @@ -273,6 +279,9 @@ private CreateAttributeOptions BuildCreateOptions()
MaxSizeKb = MaxSizeKb,
CanStoreFullImage = CanStoreFullImage,

// Formula
FormulaDefinition = FormulaDefinition,

// Shared metadata properties
IsAuditable = IsAuditable,
IsSearchable = IsSearchable,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -145,15 +145,17 @@ public async Task CreateAttributeAsync(
switch (options.Type)
{
case "string":
await ExecuteCreateAttribute(conn, options, new StringAttributeMetadata
var strMeta = new StringAttributeMetadata
{
SchemaName = options.SchemaName,
DisplayName = displayLabel,
Description = descriptionLabel,
RequiredLevel = requiredLevel,
MaxLength = options.MaxLength ?? 200,
FormatName = options.StringFormat is not null ? MapStringFormat(options.StringFormat) : StringFormatName.Text
}, ct).ConfigureAwait(false);
};
if (options.FormulaDefinition is not null) { strMeta.SourceType = 3; strMeta.FormulaDefinition = options.FormulaDefinition; }
await ExecuteCreateAttribute(conn, options, strMeta, ct).ConfigureAwait(false);
break;

case "memo":
Expand All @@ -178,6 +180,7 @@ public async Task CreateAttributeAsync(
if (options.MinValue.HasValue) intMeta.MinValue = (int)options.MinValue.Value;
if (options.MaxValue.HasValue) intMeta.MaxValue = (int)options.MaxValue.Value;
if (options.NumberFormat.HasValue()) intMeta.Format = MapIntegerFormat(options.NumberFormat!);
if (options.FormulaDefinition is not null) { intMeta.SourceType = 3; intMeta.FormulaDefinition = options.FormulaDefinition; }
await ExecuteCreateAttribute(conn, options, intMeta, ct).ConfigureAwait(false);
break;

Expand All @@ -192,6 +195,7 @@ public async Task CreateAttributeAsync(
if (options.MinValue.HasValue) decMeta.MinValue = (decimal)options.MinValue.Value;
if (options.MaxValue.HasValue) decMeta.MaxValue = (decimal)options.MaxValue.Value;
if (options.Precision.HasValue) decMeta.Precision = options.Precision.Value;
if (options.FormulaDefinition is not null) { decMeta.SourceType = 3; decMeta.FormulaDefinition = options.FormulaDefinition; }
await ExecuteCreateAttribute(conn, options, decMeta, ct).ConfigureAwait(false);
break;

Expand All @@ -206,6 +210,7 @@ public async Task CreateAttributeAsync(
if (options.MinValue.HasValue) dblMeta.MinValue = options.MinValue.Value;
if (options.MaxValue.HasValue) dblMeta.MaxValue = options.MaxValue.Value;
if (options.Precision.HasValue) dblMeta.Precision = options.Precision.Value;
if (options.FormulaDefinition is not null) { dblMeta.SourceType = 3; dblMeta.FormulaDefinition = options.FormulaDefinition; }
await ExecuteCreateAttribute(conn, options, dblMeta, ct).ConfigureAwait(false);
break;

Expand All @@ -221,11 +226,12 @@ public async Task CreateAttributeAsync(
if (options.MaxValue.HasValue) moneyMeta.MaxValue = options.MaxValue.Value;
if (options.Precision.HasValue) moneyMeta.Precision = options.Precision.Value;
if (options.PrecisionSource.HasValue) moneyMeta.PrecisionSource = options.PrecisionSource.Value;
if (options.FormulaDefinition is not null) { moneyMeta.SourceType = 3; moneyMeta.FormulaDefinition = options.FormulaDefinition; }
await ExecuteCreateAttribute(conn, options, moneyMeta, ct).ConfigureAwait(false);
break;

case "bool":
await ExecuteCreateAttribute(conn, options, new BooleanAttributeMetadata
var boolMeta = new BooleanAttributeMetadata
{
SchemaName = options.SchemaName,
DisplayName = displayLabel,
Expand All @@ -234,7 +240,9 @@ public async Task CreateAttributeAsync(
OptionSet = new BooleanOptionSetMetadata(
new OptionMetadata(new Label(options.TrueLabel, 1033), 1),
new OptionMetadata(new Label(options.FalseLabel, 1033), 0))
}, ct).ConfigureAwait(false);
};
if (options.FormulaDefinition is not null) { boolMeta.SourceType = 3; boolMeta.FormulaDefinition = options.FormulaDefinition; }
await ExecuteCreateAttribute(conn, options, boolMeta, ct).ConfigureAwait(false);
break;

case "datetime":
Expand All @@ -248,6 +256,7 @@ public async Task CreateAttributeAsync(
};
if (options.DateTimeBehavior is not null)
dtMeta.DateTimeBehavior = MapDateTimeBehavior(options.DateTimeBehavior);
if (options.FormulaDefinition is not null) { dtMeta.SourceType = 3; dtMeta.FormulaDefinition = options.FormulaDefinition; }
await ExecuteCreateAttribute(conn, options, dtMeta, ct).ConfigureAwait(false);
break;

Expand Down Expand Up @@ -919,6 +928,7 @@ private static async Task CreatePicklistAttribute(
picklistMeta.OptionSet = BuildLocalOptionSet(options);
}

if (options.FormulaDefinition is not null) { picklistMeta.SourceType = 3; picklistMeta.FormulaDefinition = options.FormulaDefinition; }
await ExecuteCreateAttribute(conn, options, picklistMeta, ct).ConfigureAwait(false);
}

Expand All @@ -944,6 +954,7 @@ private static async Task CreateMultiSelectPicklistAttribute(
multiMeta.OptionSet = BuildLocalOptionSet(options);
}

if (options.FormulaDefinition is not null) { multiMeta.SourceType = 3; multiMeta.FormulaDefinition = options.FormulaDefinition; }
await ExecuteCreateAttribute(conn, options, multiMeta, ct).ConfigureAwait(false);
}

Expand Down