ZuloOne
English
Sign in
Menu

Add computed list columns

Updated

A model can offer columns for another dictionary's list that are computed, not stored: the price of a price type, the stock in a store. The user adds them in Column setup → Computed. This page is the recipe. The contract, the endpoints, and the worked HTTP example are Computed list columns.

Note

Do not add a stored field for a value that already lives elsewhere. A new price type or a new store must appear as a parameter record, not as a schema change.

How to#

1. The service — implement IListColumnProvider on a model service (the same pattern as IFiscalCalendar). Inventory's ItemListColumns is the worked example: Price parameterized by PriceType, Stock by Store (optional, with an "all stores" caption).

public partial class ItemListColumns : IListColumnProvider
{
    private readonly ISqlService _sql;
    public ItemListColumns(ISqlService sql) => _sql = sql;

    public IReadOnlyList<ListColumnDefinition> ColumnsFor(string objectName)
        => objectName == "Item" ? ItemColumns : [];

    public async Task<IReadOnlyDictionary<Guid, object?>> ValuesAsync(
        string objectName, string key, Guid? parameter,
        IReadOnlyList<Guid> ids, DateTime asOf, CancellationToken ct = default)
        => key switch
        {
            "Price" => parameter is Guid type
                ? await PricesAsync(type, ids, asOf) : new Dictionary<Guid, object?>(),
            "Stock" => await StockAsync(parameter, ids, asOf),
            _ => new Dictionary<Guid, object?>(),
        };
}

ColumnsFor returns the catalogue for that object, empty otherwise. ValuesAsync is called once per column per page — read the whole ids list in one query (or in chunks of a few hundred). Answer with a dictionary keyed by row id; a missing id renders empty. Do not throw for "no value". asOf is a date; the list sends today.

Every implementation is asked, so another model can offer reserves on the same Item list. The provider is named by its implementation type (ItemListColumns).

2. Bump modelVersion in the same change.

Warning

Inject platform services in the constructor (ISqlService, IDictionaryManager<T>). Resolve other model services inside the method with ScriptServices.Get<IPricingService>(). A model service in the constructor is not in the DI container: the provider cannot be created, its columns disappear from Computed, and the log has List column provider ItemListColumns could not be created. Other providers still answer.

What's not there yet#

No filter or sort on a computed column. No date picker (always today). Document journals do not ask providers. Not exported to Excel. Details: Computed list columns.

Where next#

Was this page helpful?