Skip to content

Commit

Permalink
FOCUS #319: Track (sometimes differing) commitment burndown units sep…
Browse files Browse the repository at this point in the history
…arately from consumed quantity/unit columns (#400)

**Lead Maintainers**: Chris Harris, @cnharris10, Irena Jurica, @ijurica
### Documents: 
* **PR**:
[#400](#400)
Commitment Utilization and Normalization
* **PR**:
[#524](#524)
rename Commitment-Based Discount to Commitment-Discount by
[christopher.harris@datadoghq.com](mailto:christopher.harris@datadoghq.com)
* [Usage vs Pricing Quantity and unit
examples](https://docs.google.com/spreadsheets/d/1zA0brhrEntfWlzt5VNcNLBFnKPEiarajTF84o4ATeEw/edit?gid=1705742856#gid=1705742856)
*
[24.07.21-CommitmentUtilization-sample-datasets](https://docs.google.com/spreadsheets/d/1AYDPZ4rl90PPEbyQJUaGCUSwZ4s_sfy-8sO2KyNq0aM/edit?usp=drive_link)
*
[#400-commitment-utilization](https://drive.google.com/drive/u/0/folders/1u4_rc6TAqgMwuIQEKUVIX3zAzyvLM7Dj)
folder
* Document: [24.09.08 - Commitment utilization
discussion](https://docs.google.com/document/d/1bOD6MYoFi0fX-MgLyN-hxUpNOSfojlsL0MSt3menOxk/edit?usp=sharing)
* **Slack channel**:
[#tf-commitment-utilization](https://f2-focus.slack.com/archives/C07CPAQDN75)
* Approval deadline: ~Aug 29~, Sep 5


# Related PR's (Appendices):
- #528
- #535

# Key Points
- Adds 3 new columns to track CSP usage-based and spend-based
commitments: `CommitmentDiscountConsumedQuantity`,
`CommitmentDiscountPurchasedQuantity`, `CommitmentDiscountUnit`
- `CommitmentDiscountConsumedQuantity` captures the commitment units
used or unused in a charge period.
- `CommitmentDiscountPurchasedQuantity` captures the commitment units
purchased for one-time and recurring charge periods.
- `CommitmentDiscountUnit` captures the unit that the commitment
discount specifies.
- Fixes a 1.0 bug by specifying that `ConsumedQuantity` and
`ConsumedUnit` MUST be NULL for unused commitment rows. (reference
[pr](#507))
- Further scopes the definition of `commitment discount` and `negotiated
discount` within the glossary and specifies that `CommitmentDiscount*`
columns only correspond to `commitment discounts`.

## UPDATE (8/16/24)
1. Columns renamed to: `CommitmentDiscountConsumedQuantity`,
`CommitmentDiscountUnit`, `CommitmentDiscountPurchaseQuantity`
2. `{List,Contracted}UnitPrice`, `Pricing{Quantity,Unit}` are null when
`CommitmentDiscountStatus:Unused`
3. `{List,Contracted}Cost` are 0 when `CommitmentDiscountStatus:Unused`
4. New, official glossary terms incorporated from FinOps page for
[`commitment-based
discount`](https://www.finops.org/assets/terminology/#commitment-discounts)
and [`negotiated
discount`](https://www.finops.org/assets/terminology/#cloud-cost-management-terminology)

## UPDATE (8/19/24)
1. `{List,Contracted}{Cost,UnitPrice}` and `Pricing{Quantity,Unit}`
columns now `0` or `null` when `CommitmentDiscountStatus:Unused` (TO BE
DISCUSSED in TF-1)
2. `{List,Contracted}{Cost,UnitPrice}` and `Pricing{Quantity,Unit}`
columns now in bullet-list format.
3. Correction-based normative text added by Irena.
4. This
[pr](#524)
exists to renaming all instances of
`/commitment[\-,\s]?based\sdiscount/i` to `commitment discount` (with
correct casing)

### Discussion Points (8/20/24)
1. 2 current views for columns: `{List,Contracted}{Cost,UnitPrice}` and
`Pricing{Quantity,Unit}` when `CommitmentDiscountStatus:Unused`
    a. Set all values to appropriate `null` or `0` values (current).
b. Set all values to the same values as the purchase record (if it
exists).
2. Currently, `PricingCategory MUST be "Committed" when
[CommitmentDiscountId](#commitmentdiscountid) is not null`. Should this
be changed to `Standard` for `Purchase` rows where the
`CommitmentDiscountId` is the `ResourceId`?
3. With commitment/negotiated discount definitions altered, is it clear
that current/planned `CommitmentDiscount*` columns are relevant for
commitment discounts and *not* negotiated discounts?

## UPDATE (8/21/24)
1. Includes a recurring purchase for each charge period of the term for
No/Partial Upfront commitments
- No Upfront Purchase - has all units for the charge period
- Partial Upfront Purchase - has 1/2 of the units for each charge period
2. Reverts changing guidance around these
`{List,Contracted}{Cost,UnitPrice}` and `Pricing{Quantity,Unit}`
columns.
3. Adds additional guidance commitment discount purchase is one-time vs.
recurring
4. Adds additional phrasing to differentiate commitment vs negotiated
discounts in each CommitmentDiscount* column.
5. Removes edit to resource name to further minimize pr size (for now)

## Update (8/22/24)
1. Changes to the ResourceId column have been reverted (no clause for
ResourceId to be null with an unused commitment discount)

## Update (8/31/24)
Given that this pr was not fully approved on 8/30, and there was
considerable feedback (but less time) to merge
`CommitmentDiscountConsumedQuantity` and
`CommitmentDiscountPurchasedQuantity` into 1 column, I've gone ahead
with this change to form column: `CommitmentDiscountQuantity`.

Practitioners can stil filter to purchases and committed usage like:
- Purchases: `ChargeCategory = 'Purchase' AND CommitmentDiscountId IS
NOT NULL`
- Committed Usage (Used): `ChargeCategory = 'Usage' AND
CommitmentDiscountStatus = 'Used' AND CommitmentDiscountId IS NOT NULL`
- Committed Usage (Unused): `ChargeCategory = 'Usage' AND
CommitmentDiscountStatus = 'Unused' AND CommitmentDiscountId IS NOT
NULL`.

## Update (9/3/24)
- Added a brief paragraph around size-flexibility within
`CommitmentDiscountQuantity`
- Added additional glossary terms: `size-flexibility`,
`instance-family`, `instance-type`, `instance-type-ratio`.
- `instance-type-ratio` is the proposal for a generic, "FOCUS" term for
`normalization factor` (AWS), or `size flexibility ratio` (Azure)

This change is meant to reduce the number of proposed columns *without*
changing *any* (meaningful) intent of the previous versions with 2
quantity columns. The last commit to this pr encapsulates this entire
change and can be backed out if the group does not approve of this
iteration.

## Update (9/10/24)
- Further generalize "size-flexibility" as "commitment flexibility" and
tie to provider requirements
- Further generalize unit suggestions

# Sample Data

https://docs.google.com/spreadsheets/d/1AYDPZ4rl90PPEbyQJUaGCUSwZ4s_sfy-8sO2KyNq0aM/edit?pli=1&gid=1976106562#gid=1976106562

# Normative Text (original version, adopted into pr)


https://docs.google.com/spreadsheets/d/1AYDPZ4rl90PPEbyQJUaGCUSwZ4s_sfy-8sO2KyNq0aM/edit?pli=1&gid=464941124#gid=464941124

---------

Co-authored-by: Irena Jurica <irena.jurica@neos.hr>
Co-authored-by: Udam Dewaraja <udam@finops.org>
Co-authored-by: Graham <graham_murphy@sunsuper.com.au>
Co-authored-by: Larry Advey <104788770+ljadvey@users.noreply.github.com>
Co-authored-by: Michael Flanakin <flanakin@users.noreply.github.com>
  • Loading branch information
6 people authored Sep 12, 2024
1 parent d6dc4dc commit 285dabe
Show file tree
Hide file tree
Showing 19 changed files with 197 additions and 28 deletions.
16 changes: 8 additions & 8 deletions specification/attributes/discount_handling.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
# Discount Handling

A discount is a pricing construct where providers offer a reduced price for [*services*](#glossary:service). Providers may have many types of discounts, including but not limited to commercially negotiated discounts, commitment discounts when you agree to a certain amount of usage or spend, and bundled discounts where you receive free or discounted usage of one product or *service* based on the usage of another. Discount Handling is commonly used in scenarios like verifying discounts were applied and calculating cost savings.
A discount is a pricing construct where providers offer a reduced price for [*services*](#glossary:service). Providers may have many types of discounts, including but not limited to commercially [*negotiated discounts*](#glossary:negotiated-discount), [*commitment discounts*](#glossary:commitment-discount) when you agree to a certain amount of usage or spend, and bundled discounts where you receive free or discounted usage of one product or *service* based on the usage of another. Discount Handling is commonly used in scenarios like verifying discounts were applied and calculating cost savings.

Some discount offers can be purchased from a provider to get reduced prices. The most common example is a commitment discount, where you "purchase" a commitment to use or spend a specific amount within a period. When a commitment isn't fully utilized, the unused amount reduces the potential savings from the discount and can even result in paying higher costs than without the discount. Due to this risk, unused commitment amounts need to be clearly identifiable at a granular level. To facilitate this, unused commitments are recorded with a separate row for each charge period where the commitment was not fully utilized. In order to show the impact of purchased discounts on each discounted row, discount purchases need the purchase amount the be amortized over the term the discount is applied to (e.g., 1 year) with each charge period split and applied to each row that received the discount.
Some discount offers can be purchased from a provider to get reduced prices. The most common example is a *commitment discount*, where you "purchase" a commitment to use or spend a specific amount within a period. When a commitment isn't fully utilized, the unused amount reduces the potential savings from the discount and can even result in paying higher costs than without the discount. Due to this risk, unused commitment amounts need to be clearly identifiable at a granular level. To facilitate this, unused commitments are recorded with a separate row for each charge period where the commitment was not fully utilized. To show the impact of purchased discounts on each discounted row, discount purchases need the purchase amount to be amortized over the [*term*](#glossary:term) the discount is applied to (e.g., 1 year) with each [*charge period*](#glossary:chargeperiod) split and applied to each row that received the discount.

Amortization is a process used to break down and spread purchase costs over a period of time or term of use. When a purchase is applicable to resources, like commitment discounts, the amortized cost of a resource takes the initial payment and term into account and distributes it out based on the resource's usage, attributing the prorated cost for each unit of billing. Amortization enables users of billing data to distribute purchase charges to the appropriate audience in support of cost allocation efforts. Discount Handling for purchased commitments is commonly used for scenarios like calculating utilization and implementing chargeback for the purchase amount.
Amortization is a process used to break down and spread purchase costs over a period of time or *term* of use. When a purchase is applicable to resources, like *commitment discounts*, the amortized cost of a resource takes the initial payment and *term* into account and distributes it out based on the resource's usage, attributing the prorated cost for each unit of billing. Amortization enables users of billing data to distribute purchase charges to the appropriate audience in support of cost allocation efforts. Discount Handling for purchased commitments is commonly used for scenarios like calculating utilization and implementing chargeback for the purchase amount.

While providers may use different terms to describe discounts, FOCUS identifies a discount as being a reduced price applied directly to a row. Any price or cost reductions that are awarded after the fact are identified as a "Credit" Charge Category. One example might be when a provider offers a reduced rate after passing a certain threshold of usage or spend.

Expand All @@ -29,15 +29,15 @@ Indicates how to include and apply discounts to usage charges or rows in a FOCUS
* Multiple discounts MAY apply to a row, but they MUST apply to the entire charge covered by that row.
* If a discount only applies to a portion of a charge, then the discounted portion of the charge MUST be split into a separate row.
* Each discount MUST be identifiable using existing FOCUS columns.
* Rows with a commitment discount applied to them MUST include a CommitmentDiscountId.
* Rows with a *commitment discount* applied to them MUST include a CommitmentDiscountId.
* If a provider applies a discount that cannot be represented by a FOCUS column, they SHOULD include additional columns to identify the source of the discount.
* Purchased discounts (e.g., commitment discounts) MUST be amortized.
* Purchased discounts (e.g., *commitment discounts*) MUST be amortized.
* The BilledCost MUST be 0 for any row where the commitment covers the entire cost for the charge period.
* The EffectiveCost MUST include the portion of the amortized purchase cost that applies to this row.
* The sum of the EffectiveCost for all rows where CommitmentDiscountStatus is "Used" or "Unused" for each CommitmentDiscountId over the entire duration of the commitment MUST be the same as the total BilledCost of the commitment discount.
* The CommitmentDiscountId and ResourceId MUST be set to the ID assigned to the commitment discount. ChargeCategory MUST be set to "Purchase" on rows that represent a purchase of a commitment discount.
* The sum of the EffectiveCost for all rows where CommitmentDiscountStatus is "Used" or "Unused" for each CommitmentDiscountId over the entire duration of the commitment MUST be the same as the total BilledCost of the *commitment discount*.
* The CommitmentDiscountId and ResourceId MUST be set to the ID assigned to the *commitment discount*. ChargeCategory MUST be set to "Purchase" on rows that represent a purchase of a *commitment discount*.
* CommitmentDiscountStatus MUST be "Used" for ChargeCategory "Usage" rows that received a reduced price from a commitment. CommitmentDiscountId MUST be set to the ID assigned to the discount. ResourceId MUST be set to the ID of the resource that received the discount.
* If a commitment is not fully utilized, the provider MUST include a row that represents the unused portion of the commitment for that charge period. These rows MUST be represented with CommitmentDiscountStatus set to "Unused" and ChargeCategory set to "Usage". Such rows MUST have their CommitmentDiscountId and ResourceId set to the ID assigned to the commitment discount.
* If a commitment is not fully utilized, the provider MUST include a row that represents the unused portion of the commitment for that *charge period*. These rows MUST be represented with CommitmentDiscountStatus set to "Unused" and ChargeCategory set to "Usage". Such rows MUST have their CommitmentDiscountId and ResourceId set to the ID assigned to the *commitment discount*.
* Credits that are applied after the fact MUST use a ChargeCategory of "Credit".

## Exceptions
Expand Down
2 changes: 2 additions & 0 deletions specification/columns/columns.mdpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ The FOCUS specification defines a group of columns that provide qualitative valu
!INCLUDE "commitmentdiscountname.md",1
!INCLUDE "commitmentdiscountstatus.md",1
!INCLUDE "commitmentdiscounttype.md",1
!INCLUDE "commitmentdiscountquantity.md",1
!INCLUDE "commitmentdiscountunit.md",1
!INCLUDE "consumedquantity.md",1
!INCLUDE "consumedunit.md",1
!INCLUDE "contractedcost.md",1
Expand Down
2 changes: 1 addition & 1 deletion specification/columns/commitmentdiscountcategory.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Commitment Discount Category

Commitment Discount Category indicates whether the [*commitment discount*](#glossary:commitment-discount) identified in the CommitmentDiscountId column is based on usage quantity or cost (aka "spend").
Commitment Discount Category indicates whether the [*commitment discount*](#glossary:commitment-discount)identified in the CommitmentDiscountId column is based on usage quantity or cost (aka "spend"). The CommitmentDiscountCategory column is only applicable to *commitment discounts* and not [*negotiated discounts*](#glossary:negotiated-discount).

The CommitmentDiscountCategory column MUST be present in a FOCUS dataset when the provider supports *commitment discounts*. This column MUST be of type String, MUST be null when [CommitmentDiscountId](#commitmentdiscountid) is null, and MUST NOT be null when CommitmentDiscountId is not null. The CommitmentDiscountCategory MUST be one of the allowed values.

Expand Down
4 changes: 2 additions & 2 deletions specification/columns/commitmentdiscountid.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
# Commitment Discount ID

A Commitment Discount ID is the identifier assigned to a [*commitment discount*](#glossary:commitment-discount) by the provider. Commitment Discount ID is commonly used for scenarios like chargeback for *commitments* and savings per *commitment discount*.
A Commitment Discount ID is the identifier assigned to a [*commitment discount*](#glossary:commitment-discount) by the provider. Commitment Discount ID is commonly used for scenarios like chargeback for *commitments* and savings per *commitment discount*. The CommitmentDiscountId column is only applicable to *commitment discounts* and not [*negotiated discounts*](#glossary:negotiated-discount).

The CommitmentDiscountId column MUST be present in a FOCUS dataset when the provider supports *commitment discounts*. This column MUST be of type String and MUST NOT contain null values when a charge is related to a *commitment discount*. When a charge is not associated with a *commitment discount*, the column MUST be null. CommitmentDiscountId MUST be unique within the provider.
The CommitmentDiscountId column MUST be present in a FOCUS dataset when the provider supports *commitment discounts*. This column MUST be of type String and MUST NOT contain null values when a charge is related to a *commitment discount*. When a charge is not associated with a *commitment discount*, the column MUST be null. CommitmentDiscountId MUST ensure global uniqueness within the provider and SHOULD be a fully-qualified identifier.

## Column ID

Expand Down
2 changes: 1 addition & 1 deletion specification/columns/commitmentdiscountname.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Commitment Discount Name

A Commitment Discount Name is the display name assigned to a [*commitment discount*](#glossary:commitment-discount).
A Commitment Discount Name is the display name assigned to a [*commitment discount*](#glossary:commitment-discount). The CommitmentDiscountName column is only applicable to *commitment discounts* and not [*negotiated discounts*](#glossary:negotiated-discount).

The CommitmentDiscountName column MUST be present in a FOCUS dataset when the provider supports *commitment discounts*. This column MUST be of type String. The CommitmentDiscountName value MUST be null if the charge is not related to a *commitment discount* and MAY be null if a display name cannot be assigned to a *commitment discount*. CommitmentDiscountName MUST NOT be null if a display name can be assigned to a *commitment discount*.

Expand Down
52 changes: 52 additions & 0 deletions specification/columns/commitmentdiscountquantity.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
# Commitment Discount Quantity

Commitment Discount Quantity is the amount of a [*commitment discount*](#commitment-discount) purchased or accounted for in *commitment discount* related [*rows*](#glossary:row) that is denominated in [*Commitment Discount Units*](#glossary:commitmentdiscountunit). The aggregated Commitment Discount Quantity across purchase records, pertaining to a particular [Commitment Discount ID](#commitmentdiscountid) during its [*term*](#glossary:term), represents the total *Commitment Discount Units* acquired with that commitment discount. For committed usage, the Commitment Discount Quantity is either the number of *Commitment Discount Units* consumed by a [*row*](glossary:#row) that is covered by a *commitment discount* or is the unused portion of a *commitment discount* over a *charge period*. Commitment Discount Quantity is commonly used in *commitment discount* analysis and optimization use cases and only applies to *commitment discounts*, not [*negotiated discounts*](#glossary:negotiated-discount).

When *CommitmentDiscountCategory* is "Usage" (usage-based *commitment discounts*), the Commitment Discount Quantity reflects the predefined amount of usage purchased or consumed. If *commitment flexibility* is applicable, this value may be further transformed based on additional, provider-specific requirements. When *CommitmentDiscountCategory* is "Spend" (spend-based *commitment discounts*), the Commitment Discount Quantity reflects the predefined amount of spend purchased or consumed.

**Important:** When aggregating Commitment Discount Quantity for utilization calculations, it's important to exclude *commitment discount* purchases (i.e. when *ChargeCategory* is "Purchase") that are paid to cover future eligible charges (e.g., *Commitment Discount*). This exclusion helps prevent double counting of these quantities in the aggregation.

The CommitmentDiscountQuantity column adheres to the following requirements:

* CommitmentDiscountQuantity MUST be present in a FOCUS dataset when the provider supports *commitment discounts*.
* CommitmentDiscountQuantity MUST be of type Decimal and MUST conform to [Numeric Format](#numericformat) requirements.
* CommitmentDiscountQuantity MAY be negative if [*ChargeClass*](#chargeclass) is "Correction".

In cases where the *ChargeCategory* is "Purchase" and [*CommitmentDiscountId*](#commitmentdiscountid) is not null, the following applies:

* When [*ChargeFrequency*](#chargefrequency) is "One-Time", and *CommitmentDiscountId* is not null, CommitmentDiscountQuantity MUST be the positive quantity of *CommitmentDiscountUnits*, paid fully or partially upfront, that is eligible for consumption over the *commitment discount's* *term*.
* When *ChargeFrequency* is "Recurring", and *CommitmentDiscountId* is not null, CommitmentDiscountQuantity MUST be the positive quantity of *CommitmentDiscountUnits* that is eligible for consumption for each *charge period* that corresponds with the purchase.

In cases where the *ChargeCategory* is "Usage" and *CommitmentDiscountId* is not null, the following applies:

* When *CommitmentDiscountStatus* is "Used", and *ChargeClass* is not "Correction", CommitmentDiscountQuantity MUST be the positive, metered quantity of *CommitmentDiscountUnits* that is consumed over the *row's* *charge period*.
* When *CommitmentDiscountStatus* is "Unused", and *ChargeClass* is not "Correction", CommitmentDiscountQuantity MUST be the remaining, positive, unused quantity of *CommitmentDiscountUnits* for the *row's* *charge period*.

CommitmentDiscountQuantity MUST be null for all other *ChargeCategory* values.

## Column ID

CommitmentDiscountQuantity

## Display Name

Commitment Discount Quantity

## Description

The amount of a *commitment discount* purchased or accounted for in *commitment discount* related *rows* that is denominated in *Commitment Discount Units*.

## Content constraints

| Constraint | Value |
|:----------------|:-----------------|
| Column type | Dimension |
| Feature level | Conditional |
| Allows nulls | True |
| Data type | Decimal |
| Value format | [Numeric Format](#numericformat) |
| Number range | Any valid decimal value |

## Introduced (version)

1.1
2 changes: 1 addition & 1 deletion specification/columns/commitmentdiscountstatus.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Commitment Discount Status

Commitment Discount Status indicates whether the charge corresponds with the consumption of the [*commitment discount*](#glossary:commitment-discount) identified in the CommitmentDiscountId column or the unused portion of the committed amount.
Commitment Discount Status indicates whether the charge corresponds with the consumption of a [*commitment discount*](#glossary:commitment-discount) identified in the CommitmentDiscountId column or the unused portion of the committed amount. The CommitmetnDiscountStatus column is only applicable to *commitment discounts* and not [*negotiated discounts*](#glossary:negotiated-discount).

The CommitmentDiscountStatus column MUST be present in a FOCUS dataset when the provider supports *commitment discounts*. This column MUST be of type String, MUST be null when [CommitmentDiscountId](#commitmentdiscountid) is null, and MUST NOT be null when CommitmentDiscountId is not null and [Charge Category](#chargecategory) is "Usage". The CommitmentDiscountCategory MUST be one of the allowed values.

Expand Down
2 changes: 1 addition & 1 deletion specification/columns/commitmentdiscounttype.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Commitment Discount Type

Commitment Discount Type is a provider-assigned name to identify the type of [*commitment discount*](#glossary:commitment-discount) applied to the [*row*](#glossary:row).
Commitment Discount Type is a provider-assigned name to identify the type of [*commitment discount*](#glossary:commitment-discount) applied to the [*row*](#glossary:row). The CommitmentDiscountType column is only applicable to *commitment discounts* and not [*negotiated discounts*](#glossary:negotiated-discount).

The CommitmentDiscountType column MUST be present in a FOCUS dataset when the provider supports *commitment discounts*. This column MUST be of type String, MUST be null when [CommitmentDiscountId](#commitmentdiscountid) is null, and MUST NOT be null when CommitmentDiscountId is not null.

Expand Down
42 changes: 42 additions & 0 deletions specification/columns/commitmentdiscountunit.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# Commitment Discount Unit

Commitment Discount Unit represents the provider-specified measurement unit indicating how a provider measures the [Commitment Discount Quantity](#commitmentdiscountquantity) of a [*commitment discount*](#glossary:commitment-discount). The CommitmentDiscountUnit column is only applicable to *commitment discounts* and not [*negotiated discounts*](#glossary:negotiated-discount).

The CommitmentDiscountUnit column adheres to the following requirements:

* CommitmentDiscountUnit MUST be present in a FOCUS dataset when the provider supports [*commitment discounts*](#glossary:commitment-discount).
* CommitmentDiscountUnit MUST be of type String, and the units of measure used in CommitmentDiscountUnit SHOULD adhere to the values and format requirements specified in the [UnitFormat](#unitformat) attribute.
* The CommitmentDiscountUnit MUST be the same across all *rows* where *CommitmentDiscountQuantity* has the same [*CommitmentDiscountId*](#commitmentdiscountid).
* CommitmentDiscountUnit MUST NOT be null when *CommitmentDiscountId* is not null.
* CommitmentDiscountUnit MUST be null in all other cases.

In cases where the CommitmentDiscountUnit is not null, the following applies:

* The CommitmentDiscountUnit MUST represent the unit used to measure the *commitment discount*.
* When accounting for *commitment flexibility*, the CommitmentDiscountUnit value SHOULD reflect this consideration.

## Column ID

CommitmentDiscountUnit

## Display Name

Commitment Discount Unit

## Description

The provider-specified measurement unit indicating how a provider measures the *Commitment Discount Quantity* of a *commitment discount*.

## Content constraints

| Constraint | Value |
|:----------------|:-----------------|
| Column type | Dimension |
| Feature level | Conditional |
| Allows nulls | True |
| Data type | String |
| Value format | [Unit Format](#unitformat)|

## Introduced (version)

1.1
Loading

0 comments on commit 285dabe

Please sign in to comment.