From a537e835db4044aebad876ada7419a25eee2726f Mon Sep 17 00:00:00 2001 From: Nik Richers Date: Mon, 11 May 2026 16:26:39 -0700 Subject: [PATCH 1/7] docs: Calculated fields formula reference (sc-15979) Rewrites the Calculation field type docs in a Starlark-first voice and adds a built-in helper-functions table. Updates the worked Risk Tier, Next Review Date, and Days Remaining examples to dict-access params and the new helpers; each example was verified through the canonical transpile() and StarlarkExecutor.run() pipeline from validmind/backend@origin/main. Adds a single note callout in the Calculation entry that names the engine and confirms stored formulas were migrated automatically. Removes the three calculated-field screenshots pending the locked editor UI. --- ...le-next-review-date-and-days-remaining.qmd | 87 ++++--------- site/guide/inventory/_field-types.qmd | 118 ++++++++++-------- 2 files changed, 89 insertions(+), 116 deletions(-) diff --git a/site/guide/inventory/_example-next-review-date-and-days-remaining.qmd b/site/guide/inventory/_example-next-review-date-and-days-remaining.qmd index d469087fd..dff58583f 100644 --- a/site/guide/inventory/_example-next-review-date-and-days-remaining.qmd +++ b/site/guide/inventory/_example-next-review-date-and-days-remaining.qmd @@ -11,15 +11,12 @@ SPDX-License-Identifier: AGPL-3.0 AND ValidMind Commercial --> Combining different inventory field types provides a flexible way to automatically track record review schedules. This example creates fields that calculate the next review date based on approval date and validation frequency, adjusted by risk tier, and then computes the days remaining until that review. -Common date and time field types available in your formulas include: +The formulas below use a few of the built-in [helper functions](/guide/inventory/manage-inventory-fields.qmd#calculation-helpers) for working with dates: -- `vm_today` — Today's date (updates each time the formula runs) -- `date` — Python's `datetime.date` class -- `datetime` — Python's `datetime.datetime` class -- `timedelta` — Duration in days, seconds, or microseconds -- `relativedelta` — Duration in months, years, etc. (from `dateutil`) - -Here, we show you how to use `date`, `relativedelta`, and `vm_today`. +- `today()` — Today's date as an ISO string (`"YYYY-MM-DD"`). +- `safe_parse_date(value)` — Parses ISO dates/datetimes or millisecond/second epoch timestamps into an ISO string. +- `add_months(date, n)` — Adds `n` months to an ISO date. +- `days_between(a, b)` — Returns the number of days between two ISO dates. #### Calculate the next review date @@ -34,14 +31,14 @@ Determine the next review date based on an approval date and a frequency of vali - Yearly 3. Create a `Risk Tier` calculation field that depends on the frequency of validation: - + ```python def formula(params): - if params.frequencyOfValidation == "Weekly": + if params["frequencyOfValidation"] == "Weekly": return "Tier 1" - elif params.frequencyOfValidation == "Monthly": + elif params["frequencyOfValidation"] == "Monthly": return "Tier 2" - elif params.frequencyOfValidation == "Yearly": + elif params["frequencyOfValidation"] == "Yearly": return "Tier 3" else: return "N/A" @@ -51,42 +48,23 @@ Determine the next review date based on an approval date and a frequency of vali ```python def formula(params): - """ - Calculate the next review date based on the approval date and review frequency. - - Args: - params.dmApprovedDate (str): The approval date in 'YYYY-MM-DD' format. - params.dmRiskTier (string): The review tier (Tier 1, Tier 2, or Tier 3). - - Returns: - datetime: The next review date. - """ - # Guard against empty dates - if params.dmApprovedDate == "": + if params["dmApprovedDate"] == "": return "N/A" - - # Convert the approved_on date string to a datetime object - approved_date = date.fromtimestamp((int(params.dmApprovedDate))/1000) - - # Define the review frequency mapping + + approved_date = safe_parse_date(params["dmApprovedDate"]) + review_frequency = { - "Tier 1": relativedelta(months=3), # Quarterly - "Tier 2": relativedelta(months=6), # Semi-annually - "Tier 3": relativedelta(years=1), # Annually + "Tier 1": 3, # Quarterly + "Tier 2": 6, # Semi-annually + "Tier 3": 12, # Annually } - - # Get the appropriate time delta based on the tier - frequency = review_frequency.get(params.dmRiskTier) - if not frequency: - # "Invalid tier. Must be Tier 1, Tier 2, or Tier 3." + + months = review_frequency.get(params["dmRiskTier"]) + if not months: return "N/A" - - # Calculate the next review date - next_review_date = approved_date + frequency - return next_review_date.isoformat() - ``` -![Adding a calculation type field that automatically calculates the next review date](calculation-field-next-review-date.png){fig-alt="A screenshot showing the screen for adding a calculation type field that automatically calculates the next review date" width=90% .screenshot} + return add_months(approved_date, months) + ``` You can now determine the next review date in workflows by making a workflow depend on `Approved Date`. To test, change the `Approved Date` after the fact and see how `Next Review Date` changes. @@ -96,28 +74,13 @@ You can now determine the next review date in workflows by making a workflow dep ```python def formula(params): - """ - Calculate days remaining until the next review. - - Args: - params.nextReviewDate (str): The next review date in ISO format. - - Returns: - str: Days remaining until review (example:"45 days remaining"). - """ - # Get next review date (stored as ISO format string) - next_review_date = getattr(params, "nextReviewDate", "") + next_review_date = params.get("nextReviewDate", "") if not next_review_date: return "Not applicable" - next_review = date.fromisoformat(next_review_date) - - # Calculate days until review using built-in vm_today - difference = next_review - vm_today - return f"{difference.days} days remaining" - ``` - -![Adding a calculation type field that automatically calculates the days remaining until the next review](calculation-field-days-remaining.png){fig-alt="A screenshot showing the screen for adding a calculation type field that automatically calculates the days remaining until the next review" width=90% .screenshot} + difference = days_between(next_review_date, today()) + return "%d days remaining" % difference + ``` You can now check the number of days remaining until the next review. ::: diff --git a/site/guide/inventory/_field-types.qmd b/site/guide/inventory/_field-types.qmd index 619e33d3d..c66ee9056 100644 --- a/site/guide/inventory/_field-types.qmd +++ b/site/guide/inventory/_field-types.qmd @@ -66,11 +66,35 @@ Attachments :::: Calculation -: Define a `formula(params)` function that automatically calculates and returns a read-only value based on the params dictionary, which includes selected custom field keys retrieved from your other inventory record fields. +: Define a `formula(params)` function that reads field values from the `params` dictionary and returns a read-only value. Formulas are written in [Starlark](https://github.com/bazelbuild/starlark), a small, sandboxed scripting language with a Python-style syntax and a set of built-in helper functions for working with dates, numbers, and lists. + +::: {.callout title="A note on calculated fields"} +{{< var vm.product >}} runs calculated field formulas on the Starlark formula engine. Formulas authored on earlier releases were written in Python and have been migrated to Starlark automatically — your stored formulas continue to evaluate without changes, and you only need to use Starlark syntax when creating or editing formulas going forward. +::: + +##### Available helpers {#calculation-helpers} + +Reference these helpers in your formulas — they cover the date, number, and list operations the engine does not expose directly: + +| Helper | Returns | Description | +|---|---|---| +| `today()` | `"YYYY-MM-DD"` | Current date as an ISO string. | +| `safe_parse_date(value, default=None)` | `"YYYY-MM-DD"` or `default` | Parses ISO dates/datetimes or millisecond/second epoch timestamps. | +| `to_iso(value)` | `"YYYY-MM-DD"` or `None` | Alias for `safe_parse_date` with no default. | +| `add_days(date, n)` | `"YYYY-MM-DD"` or `None` | Adds `n` days to an ISO date. | +| `add_months(date, n)` | `"YYYY-MM-DD"` or `None` | Adds `n` months to an ISO date. | +| `days_between(a, b)` | `int` or `None` | Days between two ISO dates (`a` − `b`). | +| `days_since(date)` | `int` or `None` | Days from `date` to today. | +| `months_between(a, b)` | `int` or `None` | Full-month difference between two ISO dates. | +| `get_year(date)` / `get_month(date)` / `get_day(date)` | `int` or `None` | Components of an ISO date. | +| `safe_int(value, default=0)` | `int` | Tolerates strings and missing values. | +| `safe_float(value, default=0.0)` | `float` | Tolerates strings and missing values. | +| `list_count(list, value)` | `int` | Number of times `value` appears in `list`. | +| `zfill(value, width)` | `string` | Zero-pads `value` to `width` characters. | :::: {.content-visible when-format="html" when-meta="includes.inventory"} 1. Select from the drop-down of **[available record fields]{.smallcaps}** to allow your formula access to the field's values.^[Fields are grouped by field type.] -2. Replace the demonstration formula with your own in the code box provided.^[**Stick to basic operations**.
Keep your code simple and avoid complex logic and imports.] +2. Replace the demonstration formula with your own in the code box provided.^[Reference fields with dictionary-style access — `params["fieldKey"]` — and reach for the [available helpers](#calculation-helpers) for date and number work.] 3. Click **Test Calculation {{< fa angle-down >}}** to open the testing area. 4. Enter sample values in the testing area then click **{{< fa play >}} Test Calculation** to validate your formula.

@@ -80,38 +104,29 @@ Calculation ### Example — Risk tier calculation -You have numeric inventory fields of `materiality` and `complexity`, where a larger value indicates a lower risk. +You have inventory fields named `materiality` and `complexity` that classify a record's risk. ##### Example formula -You want a calculated field that automatically returns a risk score based on `materiality` and `complexity`: +A calculated field that returns a combined risk tier based on `materiality` and `complexity`: ```python - def formula(params): - # High Risk: If materiality is high risk, return high risk regardless of complexity - if params.materiality == "High Risk": - return "High Risk" - # Medium Risk: If materiality is low risk but complexity is high risk, return medium risk - if params.materiality == "Low Risk" and params.complexity == "High Risk": - return "Medium Risk" - # Low Risk: Both materiality and complexity are low risk - return "Low Risk" +def formula(params): + if params["materiality"] == "High Risk": + return "High Risk" + if params["materiality"] == "Low Risk" and params["complexity"] == "High Risk": + return "Medium Risk" + return "Low Risk" ``` -##### Example Calculation field configuration - -Your calculated field is grouped under `Model Risk` inventory fields, and can only be manually overridden by that record's Validators: - -![Adding a calculation type field that automatically calculates risk tier](calculation-field.png){fig-alt="A screenshot showing the screen for adding a calculation type field that automatically calculates risk tier" width=90% .screenshot} - ::: ::: :::: :::: {.content-visible when-format="html" when-meta="includes.artifacts"} -1. Select from the drop-down of **[available artifact fields]{.smallcaps}** and **[record fields available via]{.smallcaps} `params.model`** to allow your formula access to the field's values.^[Fields are grouped by field type.] -2. Replace the demonstration formula with your own in the code box provided.^[**Stick to basic operations**.
Keep your code simple and avoid complex logic and imports.] +1. Select from the drop-down of **[available artifact fields]{.smallcaps}** and **[record fields available via]{.smallcaps} `params["model"]`** to allow your formula access to the field's values.^[Fields are grouped by field type.] +2. Replace the demonstration formula with your own in the code box provided.^[Reference fields with dictionary-style access — `params["fieldKey"]` and `params["model"]["fieldKey"]` for parent inventory record data — and reach for the [available helpers](#calculation-helpers) for date and number work.] 4. Click **Test Calculation {{< fa angle-down >}}** to open the testing area. 5. Enter in sample values in the testing area then click **{{< fa play >}} Test Calculation** to validate your formula.

@@ -121,10 +136,10 @@ Your calculated field is grouped under `Model Risk` inventory fields, and can on ### Example — Use artifact types in your formulas to create dynamic calculations -Use simple dot notation to include [artifact types](/guide/validation/manage-artifact-types.qmd){target="_blank"}: +The [artifact type](/guide/validation/manage-artifact-types.qmd){target="_blank"} is exposed under `params["finding_type"]` so you can branch on it: -- `finding_type.tag` — Technical tag: `VALIDATION_ISSUE` -- `finding_type.name` — Human-readable name: `Validation Issue` +- `params["finding_type"]["tag"]` — Technical tag: `VALIDATION_ISSUE` +- `params["finding_type"]["name"]` — Human-readable name: `Validation Issue` ##### Example use cases @@ -138,44 +153,39 @@ Use simple dot notation to include [artifact types](/guide/validation/manage-art #### Severity calculation ```python -# Calculate different severity scores based on artifact type - -if finding_type.tag == "VALIDATION_ISSUE": - return severity_score * 2.5 -elif finding_type.tag == "POLICY_EXCEPTION": - return severity_score * 1.0 -else: - return severity_score * 1.8 +def formula(params): + if params["finding_type"]["tag"] == "VALIDATION_ISSUE": + return params["severity_score"] * 2.5 + elif params["finding_type"]["tag"] == "POLICY_EXCEPTION": + return params["severity_score"] * 1.0 + else: + return params["severity_score"] * 1.8 ``` #### Due date calculation ```python -# Dynamically calculate due dates based on artifact type - -base_days = 30 -if finding_type.tag == "VALIDATION_ISSUE": - urgency_multiplier = 0.5 # 15 days -elif finding_type.tag == "MODEL_LIMITATION": - urgency_multiplier = 2.0 # 60 days -else: - urgency_multiplier = 1.0 # 30 days - -return base_days * urgency_multiplier +def formula(params): + base_days = 30 + if params["finding_type"]["tag"] == "VALIDATION_ISSUE": + urgency_multiplier = 0.5 + elif params["finding_type"]["tag"] == "MODEL_LIMITATION": + urgency_multiplier = 2.0 + else: + urgency_multiplier = 1.0 + return base_days * urgency_multiplier ``` #### Custom fields & parent record data ```python -# Combine artifact types with custom fields and parent record data - -risk_factor = custom_field_risk_score or 1.0 -model_criticality = params.model.get("criticality_level", "medium") - -if finding_type.tag == "VALIDATION_ISSUE" and model_criticality == "high": - return risk_factor * 3.0 -else: - return risk_factor * 1.5 +def formula(params): + risk_factor = params["custom_field_risk_score"] or 1.0 + model_criticality = params["model"].get("criticality_level", "medium") + if params["finding_type"]["tag"] == "VALIDATION_ISSUE" and model_criticality == "high": + return risk_factor * 3.0 + else: + return risk_factor * 1.5 ``` ::: @@ -251,9 +261,9 @@ Attachments : Upload supporting files for your [record](/guide/inventory/edit-inventory-fields.qmd#manage-attachments){target="_blank"} or [artifact](/guide/validation/add-manage-artifacts.qmd#manage-attachments){target="_blank"}. Files must be less than 50 MB each in size. Calculation -: Define a `formula(params)` function that automatically calculates and returns a read-only value based on the params dictionary, which includes selected custom field keys retrieved from your other inventory record fields. +: Define a `formula(params)` function that reads field values from the `params` dictionary (`params["fieldKey"]`) and returns a read-only value. Formulas are written in Starlark and have access to a set of built-in helpers for dates, numbers, and lists. - 1. Select from the drop-down of **[available record fields]{.smallcaps}**, or **[available artifact fields]{.smallcaps}** and **[record fields available via]{.smallcaps} `params.model`** (artifact fields) to allow your formula access to the field's values. + 1. Select from the drop-down of **[available record fields]{.smallcaps}**, or **[available artifact fields]{.smallcaps}** and **[record fields available via]{.smallcaps} `params["model"]`** (artifact fields) to allow your formula access to the field's values. 2. Replace the demonstration formula with your own in the code box provided. 4. Click **Test Calculation {{< fa angle-down >}}** to open the testing area. 5. Enter in sample values in the testing area then click **{{< fa play >}} Test Calculation** to validate your formula. From 457bf13065ffd2a47980b2faed2f4fde9f0bc7bc Mon Sep 17 00:00:00 2001 From: Nik Richers Date: Mon, 11 May 2026 17:11:56 -0700 Subject: [PATCH 2/7] Edits --- .../inventory/_example-next-review-date-and-days-remaining.qmd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/site/guide/inventory/_example-next-review-date-and-days-remaining.qmd b/site/guide/inventory/_example-next-review-date-and-days-remaining.qmd index dff58583f..aa1ca0ed0 100644 --- a/site/guide/inventory/_example-next-review-date-and-days-remaining.qmd +++ b/site/guide/inventory/_example-next-review-date-and-days-remaining.qmd @@ -11,7 +11,7 @@ SPDX-License-Identifier: AGPL-3.0 AND ValidMind Commercial --> Combining different inventory field types provides a flexible way to automatically track record review schedules. This example creates fields that calculate the next review date based on approval date and validation frequency, adjusted by risk tier, and then computes the days remaining until that review. -The formulas below use a few of the built-in [helper functions](/guide/inventory/manage-inventory-fields.qmd#calculation-helpers) for working with dates: +Built-in helper functions for working with dates include:^[[Calculation helpers](/guide/inventory/manage-inventory-fields.qmd#calculation-helpers)]{.smallcaps} - `today()` — Today's date as an ISO string (`"YYYY-MM-DD"`). - `safe_parse_date(value)` — Parses ISO dates/datetimes or millisecond/second epoch timestamps into an ISO string. From d2f470a11920f7bcb4959f2342ecc1da47002f6e Mon Sep 17 00:00:00 2001 From: Nik Richers Date: Mon, 11 May 2026 17:20:17 -0700 Subject: [PATCH 3/7] Put some docstrings back --- .../inventory/_example-next-review-date-and-days-remaining.qmd | 2 ++ 1 file changed, 2 insertions(+) diff --git a/site/guide/inventory/_example-next-review-date-and-days-remaining.qmd b/site/guide/inventory/_example-next-review-date-and-days-remaining.qmd index aa1ca0ed0..47d768feb 100644 --- a/site/guide/inventory/_example-next-review-date-and-days-remaining.qmd +++ b/site/guide/inventory/_example-next-review-date-and-days-remaining.qmd @@ -48,6 +48,7 @@ Determine the next review date based on an approval date and a frequency of vali ```python def formula(params): + """Return the next review date based on the approved date and risk tier.""" if params["dmApprovedDate"] == "": return "N/A" @@ -74,6 +75,7 @@ You can now determine the next review date in workflows by making a workflow dep ```python def formula(params): + """Return the number of days until the next review date.""" next_review_date = params.get("nextReviewDate", "") if not next_review_date: return "Not applicable" From 70d315b295602b34fbd4ac64cb84bf432fec52ec Mon Sep 17 00:00:00 2001 From: Nik Richers Date: Mon, 11 May 2026 17:22:28 -0700 Subject: [PATCH 4/7] Edits --- site/guide/inventory/_field-types.qmd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/site/guide/inventory/_field-types.qmd b/site/guide/inventory/_field-types.qmd index c66ee9056..679fc9f00 100644 --- a/site/guide/inventory/_field-types.qmd +++ b/site/guide/inventory/_field-types.qmd @@ -66,7 +66,7 @@ Attachments :::: Calculation -: Define a `formula(params)` function that reads field values from the `params` dictionary and returns a read-only value. Formulas are written in [Starlark](https://github.com/bazelbuild/starlark), a small, sandboxed scripting language with a Python-style syntax and a set of built-in helper functions for working with dates, numbers, and lists. +: Define a `formula(params)` function that reads field values from the `params` dictionary and returns a read-only value. Formulas are written in Starlark^[[Starlark](https://github.com/bazelbuild/starlark)], a small, sandboxed scripting language with a Python-style syntax and a set of built-in helper functions for working with dates, numbers, and lists. ::: {.callout title="A note on calculated fields"} {{< var vm.product >}} runs calculated field formulas on the Starlark formula engine. Formulas authored on earlier releases were written in Python and have been migrated to Starlark automatically — your stored formulas continue to evaluate without changes, and you only need to use Starlark syntax when creating or editing formulas going forward. From 70798ef53f854a16f84750c971c6ef31d84ef695 Mon Sep 17 00:00:00 2001 From: Nik Richers Date: Mon, 11 May 2026 17:28:00 -0700 Subject: [PATCH 5/7] Edits --- site/guide/inventory/_field-types.qmd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/site/guide/inventory/_field-types.qmd b/site/guide/inventory/_field-types.qmd index 679fc9f00..4fd172095 100644 --- a/site/guide/inventory/_field-types.qmd +++ b/site/guide/inventory/_field-types.qmd @@ -69,7 +69,7 @@ Calculation : Define a `formula(params)` function that reads field values from the `params` dictionary and returns a read-only value. Formulas are written in Starlark^[[Starlark](https://github.com/bazelbuild/starlark)], a small, sandboxed scripting language with a Python-style syntax and a set of built-in helper functions for working with dates, numbers, and lists. ::: {.callout title="A note on calculated fields"} -{{< var vm.product >}} runs calculated field formulas on the Starlark formula engine. Formulas authored on earlier releases were written in Python and have been migrated to Starlark automatically — your stored formulas continue to evaluate without changes, and you only need to use Starlark syntax when creating or editing formulas going forward. +{{< var vm.product >}} runs calculated field formulas on the Starlark formula engine. Formulas authored on earlier releases were written in Python and have been migrated to Starlark automatically. When creating or editing formulas, you now must use the Starlark syntax. ::: ##### Available helpers {#calculation-helpers} From 2a8ed608cc8d2caf3cef00ce6de8943d7c259af8 Mon Sep 17 00:00:00 2001 From: Nik Richers Date: Tue, 12 May 2026 09:25:39 -0700 Subject: [PATCH 6/7] Fix render warnings --- site/guide/inventory/_field-types.qmd | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/site/guide/inventory/_field-types.qmd b/site/guide/inventory/_field-types.qmd index 4fd172095..fecf2117e 100644 --- a/site/guide/inventory/_field-types.qmd +++ b/site/guide/inventory/_field-types.qmd @@ -94,7 +94,7 @@ Reference these helpers in your formulas — they cover the date, number, and li :::: {.content-visible when-format="html" when-meta="includes.inventory"} 1. Select from the drop-down of **[available record fields]{.smallcaps}** to allow your formula access to the field's values.^[Fields are grouped by field type.] -2. Replace the demonstration formula with your own in the code box provided.^[Reference fields with dictionary-style access — `params["fieldKey"]` — and reach for the [available helpers](#calculation-helpers) for date and number work.] +2. Replace the demonstration formula with your own in the code box provided.^[Reference fields with dictionary-style access — `params["fieldKey"]` — and use the available helpers for date and number work.] 3. Click **Test Calculation {{< fa angle-down >}}** to open the testing area. 4. Enter sample values in the testing area then click **{{< fa play >}} Test Calculation** to validate your formula.

@@ -126,7 +126,7 @@ def formula(params): :::: {.content-visible when-format="html" when-meta="includes.artifacts"} 1. Select from the drop-down of **[available artifact fields]{.smallcaps}** and **[record fields available via]{.smallcaps} `params["model"]`** to allow your formula access to the field's values.^[Fields are grouped by field type.] -2. Replace the demonstration formula with your own in the code box provided.^[Reference fields with dictionary-style access — `params["fieldKey"]` and `params["model"]["fieldKey"]` for parent inventory record data — and reach for the [available helpers](#calculation-helpers) for date and number work.] +2. Replace the demonstration formula with your own in the code box provided.^[Reference fields with dictionary-style access — `params["fieldKey"]` and `params["model"]["fieldKey"]` for parent inventory record data — and use the available helpers for date and number work. 4. Click **Test Calculation {{< fa angle-down >}}** to open the testing area. 5. Enter in sample values in the testing area then click **{{< fa play >}} Test Calculation** to validate your formula.

From 4ca0b1935daf82d5878774417de4f95ff71097ae Mon Sep 17 00:00:00 2001 From: Nik Richers Date: Tue, 12 May 2026 09:35:13 -0700 Subject: [PATCH 7/7] Remove troublemaker anchor --- .../inventory/_example-next-review-date-and-days-remaining.qmd | 2 +- site/guide/inventory/_field-types.qmd | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/site/guide/inventory/_example-next-review-date-and-days-remaining.qmd b/site/guide/inventory/_example-next-review-date-and-days-remaining.qmd index 47d768feb..0cd054d69 100644 --- a/site/guide/inventory/_example-next-review-date-and-days-remaining.qmd +++ b/site/guide/inventory/_example-next-review-date-and-days-remaining.qmd @@ -11,7 +11,7 @@ SPDX-License-Identifier: AGPL-3.0 AND ValidMind Commercial --> Combining different inventory field types provides a flexible way to automatically track record review schedules. This example creates fields that calculate the next review date based on approval date and validation frequency, adjusted by risk tier, and then computes the days remaining until that review. -Built-in helper functions for working with dates include:^[[Calculation helpers](/guide/inventory/manage-inventory-fields.qmd#calculation-helpers)]{.smallcaps} +Built-in helper functions for working with dates include: - `today()` — Today's date as an ISO string (`"YYYY-MM-DD"`). - `safe_parse_date(value)` — Parses ISO dates/datetimes or millisecond/second epoch timestamps into an ISO string. diff --git a/site/guide/inventory/_field-types.qmd b/site/guide/inventory/_field-types.qmd index fecf2117e..df5e65c8f 100644 --- a/site/guide/inventory/_field-types.qmd +++ b/site/guide/inventory/_field-types.qmd @@ -72,7 +72,7 @@ Calculation {{< var vm.product >}} runs calculated field formulas on the Starlark formula engine. Formulas authored on earlier releases were written in Python and have been migrated to Starlark automatically. When creating or editing formulas, you now must use the Starlark syntax. ::: -##### Available helpers {#calculation-helpers} +##### Available helpers Reference these helpers in your formulas — they cover the date, number, and list operations the engine does not expose directly: