From b621a1c6aabdf5e79a7fb4f45381840f560f5189 Mon Sep 17 00:00:00 2001 From: Udam Dewaraja Date: Thu, 3 Oct 2024 16:29:32 -0700 Subject: [PATCH 01/22] Cleanup Metadata PR to fix content bugs/errors, broken links, reduce nesting, formatting (#543) Fixes include fixing missing content linking, broken links, formatting, and some content bugs. --- specification/Makefile | 6 ++++ .../appendix/commitment_discounts.md | 30 +++++++++---------- specification/appendix/examples/examples.mdpp | 2 +- .../metadata/data_generator_example.md | 20 ------------- .../examples/metadata/metadata_examples.mdpp | 24 --------------- .../adding_new_columns_example.md | 10 +++---- .../changing_column_metadata_example.md | 12 ++++---- .../correcting_schema_errors_example.md | 11 ++++--- .../data_generator_example.md | 18 +++++++++++ .../focus_version_changed_example.md | 12 ++++---- ...nged_with_provider_version_used_example.md | 28 +++++++---------- .../metadata_examples/metadata_examples.mdpp | 24 +++++++++++++++ .../provider_version_changed_example.md | 15 ++++------ .../removing_columns_example.md | 10 +++---- .../schema_metadata_example.md | 10 +++---- .../schema_metadata_reference_example.md | 14 ++++----- .../data_generator/data_generator.mdpp | 2 +- specification/metadata/schema/schema.mdpp | 17 +++++------ 18 files changed, 122 insertions(+), 143 deletions(-) delete mode 100644 specification/appendix/examples/metadata/data_generator_example.md delete mode 100644 specification/appendix/examples/metadata/metadata_examples.mdpp rename specification/appendix/examples/{metadata => metadata_examples}/adding_new_columns_example.md (80%) rename specification/appendix/examples/{metadata => metadata_examples}/changing_column_metadata_example.md (83%) rename specification/appendix/examples/{metadata => metadata_examples}/correcting_schema_errors_example.md (79%) create mode 100644 specification/appendix/examples/metadata_examples/data_generator_example.md rename specification/appendix/examples/{metadata => metadata_examples}/focus_version_changed_example.md (71%) rename specification/appendix/examples/{metadata => metadata_examples}/focus_version_changed_with_provider_version_used_example.md (80%) create mode 100644 specification/appendix/examples/metadata_examples/metadata_examples.mdpp rename specification/appendix/examples/{metadata => metadata_examples}/provider_version_changed_example.md (69%) rename specification/appendix/examples/{metadata => metadata_examples}/removing_columns_example.md (86%) rename specification/appendix/examples/{metadata => metadata_examples}/schema_metadata_example.md (76%) rename specification/appendix/examples/{metadata => metadata_examples}/schema_metadata_reference_example.md (63%) diff --git a/specification/Makefile b/specification/Makefile index 0465221a0..253b32424 100644 --- a/specification/Makefile +++ b/specification/Makefile @@ -25,7 +25,13 @@ else endif ./validate_includes.py columns ./validate_includes.py attributes + ./validate_includes.py metadata + ./validate_includes.py metadata/data_generator + ./validate_includes.py metadata/schema + ./validate_includes.py metadata/schema/column_definition ./validate_includes.py appendix + ./validate_includes.py appendix/examples + ./validate_includes.py appendix/examples/metadata_examples PYTHONPATH=../vendored/ $(MARKDOWNPP) spec.mdpp -o $@ $(PYMARKDOWNLNT) --config markdownlnt.cfg scan $(SPEC_SOURCE_MDFILES) $(PYMARKDOWNLNT) --config markdownlnt.cfg scan $@ diff --git a/specification/appendix/commitment_discounts.md b/specification/appendix/commitment_discounts.md index ce9b079dd..6f83a618f 100644 --- a/specification/appendix/commitment_discounts.md +++ b/specification/appendix/commitment_discounts.md @@ -14,16 +14,16 @@ While customers are bound to the *term* of a *commitment discounts*, providers o * *No Upfront* - The *commitment discounts* is paid on a repeated basis, typically over each [*billing period*](glossary:billing-period) of the *term*. * *Partial Upfront* - Some of the *commitment discounts* is paid before the *term* begins, and the rest is paid repeatedly over the *term*. -For example, if a customer buys a 1-year, spend-based *commitment discount* with a $1.00 hourly commit and pays with the partial option, the *commitment discount's* payment consists of a one-time purchase in the beginning of the *term* *and* monthly recurring purchases with the following totals: +For example, if a customer buys a 1-year, spend-based *commitment discount* with a $1.00 hourly commit and pays with the partial option, the *commitment discount's* payment consists of a one-time purchase in the beginning of the *term* *and* monthly recurring purchases with the following totals: -1. *One-Time* - $4,380 (`24 hours * 365 days * $1.00 * 0.5`) -2. *Recurring* - $182.50 (`24 hours * 365 days * $1.00 / 12 months`) +1. *One-Time* - $4,380 (`24 hours * 365 days * $1.00 * 0.5`) +2. *Recurring* - $182.50 (`24 hours * 365 days * $1.00 / 12 months`) ## Usage Commitment discounts follow a "use-it-or-lose-it" model where the [*amortization*](glossary:amortization) of a *commitment discount's* purchase applies evenly to eligible *resources* over each [*charge period*](glossary:charge-period) of the *term*. -For example, if a customer buys a spend-based *commitment discount* with a $1.00 hourly commit in January (31 days), only $1.00 is eligible for consumption for each hourly *charge period*. If a customer has eligible *resources* running during this *charge period*, an amount of up to $1.00 will be allocated to these *resources*. Conversely, if a customer does have eligible *resources* running that fully take advantage of this $1.00 during this *charge period*, then some or all of this amount will go to waste. +For example, if a customer buys a spend-based *commitment discount* with a $1.00 hourly commit in January (31 days), only $1.00 is eligible for consumption for each hourly *charge period*. If a customer has eligible *resources* running during this *charge period*, an amount of up to $1.00 will be allocated to these *resources*. Conversely, if a customer does have eligible *resources* running that fully take advantage of this $1.00 during this *charge period*, then some or all of this amount will go to waste. ## Commitment Discounts in FOCUS @@ -35,11 +35,11 @@ All *commitment discount* purchases appear with a positive `BilledCost`, `Pricin Recurring purchases are allocated across all corresponding *charge periods* of the *term* when `ChargeCategory` is "Purchase", `ChargeFrequency` is "Recurring", and `CommitmentDiscountQuantity` and `CommitmentDiscountUnit` are reflected only for that *charge period*. -Using the same *commitment discount* example as above with a one-year, spend-based *commitment discount* with a $1.00 hourly commit purchased on Jan 1, 2023, various purchase options are available: +Using the same *commitment discount* example as above with a one-year, spend-based *commitment discount* with a $1.00 hourly commit purchased on Jan 1, 2023, various purchase options are available: #### Scenario #1: All Upfront -The entire *commitment discount* is billed _once_ during the first *charge period* of the *term* for $8,670 (derived as `24 hours * 365 days * $1.00`). +The entire *commitment discount* is billed _once_ during the first *charge period* of the *term* for $8,670 (derived as `24 hours * 365 days * $1.00`). ```json [ @@ -63,7 +63,7 @@ The entire *commitment discount* is billed _once_ during the first *charge perio #### Scenario #2: No Upfront -The *commitment discount* is billed across all 8,760 (`24 hours * 365 days`) *charge periods* of the *term* with $1.00 allocated to each *charge period* over the *term*. +The *commitment discount* is billed across all 8,760 (`24 hours * 365 days`) *charge periods* of the *term* with $1.00 allocated to each *charge period* over the *term*. ```json [ @@ -89,7 +89,7 @@ The *commitment discount* is billed across all 8,760 (`24 hours * 365 days`) *ch #### Scenario #3: Partial Upfront -With a 50/50 split, half of the commitment is billed _once_ during the first *charge period* of the *term* for $4,380 (derived as `24 hours * 182.5 days * $1.00`), and the other half is billed across each *charge period* over the term, derived as (`$1.00 * 8,760 hours * 0.5`). Amortized costs incur half of the amount (i.e. $0.50) from the one-time purchase and the other half from the recurring purchase. +With a 50/50 split, half of the commitment is billed _once_ during the first *charge period* of the *term* for $4,380 (derived as `24 hours * 182.5 days * $1.00`), and the other half is billed across each *charge period* over the term, derived as (`$1.00 * 8,760 hours * 0.5`). Amortized costs incur half of the amount (i.e. $0.50) from the one-time purchase and the other half from the recurring purchase. ```json [ @@ -130,16 +130,16 @@ With a 50/50 split, half of the commitment is billed _once_ during the first *ch ### Usage *Rows* -*Amortization* of *commitment discounts* occur similarly regardless of how *commitment discount* purchases are made. The same usage-based or spend-based amount is applied evenly across all *charge periods* and potentially allocated to eligible *resources*. Continuing with the same *commitment discount* example, a one-year, spend-based *commitment discount* with a $1.00 hourly commit and 1 *resource* (for simplicity) yields 4 types of scenarios that can occur during a *charge period*: +*Amortization* of *commitment discounts* occur similarly regardless of how *commitment discount* purchases are made. The same usage-based or spend-based amount is applied evenly across all *charge periods* and potentially allocated to eligible *resources*. Continuing with the same *commitment discount* example, a one-year, spend-based *commitment discount* with a $1.00 hourly commit and 1 *resource* (for simplicity) yields 4 types of scenarios that can occur during a *charge period*: * Scenario #1: An eligible *resource* fully consumes the allocated amount (100% utilization) * Scenario #2: No eligible *resource* consumes the allocated amount (0% utilization) * Scenario #3: An eligible *resource* partially consumes the allocated amount (75% utilization) -* Scenario #4: An eligible *resource* fully consumes the $1.00 hourly commit with an overage (100% utilization + overage) +* Scenario #4: An eligible *resource* fully consumes the $1.00 hourly commit with an overage (100% utilization + overage) #### Scenario #1: An eligible *resource* fully consumes the allocated amount (100% utilization) -In this scenario, one eligible *resource* runs for the full hour and consumes $1.00, so one *row* allocated to the *resource* is produced. +In this scenario, one eligible *resource* runs for the full hour and consumes $1.00, so one *row* allocated to the *resource* is produced. ```json [ @@ -166,7 +166,7 @@ In this scenario, one eligible *resource* runs for the full hour and consumes $1 #### Scenario #2: No eligible *resource* consumes the allocated amount (0% utilization) -In this situation, the full eligible, $1.00 amount remained unutilized and results in 1 unused *row*. In this scenario, it is important to note that while `CommitmentDiscountQuantity` is not because $1 was still drawn down by the *commitment discount* even though, no *resource* was allocated, so `ConsumedQuantity` and `ConsumedUnit` are null. +In this situation, the full eligible, $1.00 amount remained unutilized and results in 1 unused *row*. In this scenario, it is important to note that while `CommitmentDiscountQuantity` is not because $1 was still drawn down by the *commitment discount* even though, no *resource* was allocated, so `ConsumedQuantity` and `ConsumedUnit` are null. ```json [ @@ -193,7 +193,7 @@ In this situation, the full eligible, $1.00 amount remained unutilized and resul #### Scenario #3: An eligible *resource* partially consumes the allocated amount (75% utilization) -In this scenario, one eligible *resource* runs for the full hour and consumes $0.75 of the $1.00 allocation. One *row* shows $0.75 to a *resource*, and the other *row* shows that $0.25 was unused. +In this scenario, one eligible *resource* runs for the full hour and consumes $0.75 of the $1.00 allocation. One *row* shows $0.75 to a *resource*, and the other *row* shows that $0.25 was unused. ```json [ @@ -236,9 +236,9 @@ In this scenario, one eligible *resource* runs for the full hour and consumes $0 ] ``` -#### Scenario #4: An eligible *resource* fully consumes the $1.00 hourly commit with an overage (100% utilization + overage) +#### Scenario #4: An eligible *resource* fully consumes the $1.00 hourly commit with an overage (100% utilization + overage) -In this scenario, one eligible *resource* runs for the full hour and is charged $1.50. One *row* shows that $1.00 was *amortized* from the *commitment discount*, and the other shows that $0.50 was charged as standard, on-demand spend. +In this scenario, one eligible *resource* runs for the full hour and is charged $1.50. One *row* shows that $1.00 was *amortized* from the *commitment discount*, and the other shows that $0.50 was charged as standard, on-demand spend. ```json [ diff --git a/specification/appendix/examples/examples.mdpp b/specification/appendix/examples/examples.mdpp index edf59c82a..1d217f201 100644 --- a/specification/appendix/examples/examples.mdpp +++ b/specification/appendix/examples/examples.mdpp @@ -2,4 +2,4 @@ *This section is non-normative.* -!INCLUDE "metadata/metadata_examples.mdpp",1 +!INCLUDE "metadata_examples/metadata_examples.mdpp",1 diff --git a/specification/appendix/examples/metadata/data_generator_example.md b/specification/appendix/examples/metadata/data_generator_example.md deleted file mode 100644 index 932e52bb4..000000000 --- a/specification/appendix/examples/metadata/data_generator_example.md +++ /dev/null @@ -1,20 +0,0 @@ -# Data Generator Metadata - -## Scenario - -Acme provides metadata about the data generator. They provide this via the Data Generator schema object. - -## Supplied Metadata - -## Location of Data Generator Metadata File - -`/FOCUS/metadata/data_generator.json` - -## Content of Data Generator Metadata File - -```json -{ - "DataGenerator": "Acme" -} -``` - diff --git a/specification/appendix/examples/metadata/metadata_examples.mdpp b/specification/appendix/examples/metadata/metadata_examples.mdpp deleted file mode 100644 index 58d75735d..000000000 --- a/specification/appendix/examples/metadata/metadata_examples.mdpp +++ /dev/null @@ -1,24 +0,0 @@ -# Metadata Examples - -The following is an example metadata JSON structure provided by a hypothetical FOCUS data provider called ACME. This example illustrates an example of how a provider can supply the required reference between the FOCUS data and the schema metadata. Provider implementations will vary on how the metadata is stored and retrieved; however, the provider's chosen metadata delivery approach should be able to support the structure represented in this example. - -## Scenario - -In this example, the provider supports delivery of FOCUS data via file export to a data storage system. The provider delivers data every 12 hours. - -## Example Data Structure - -* export root location: `/FOCUS` -* metadata location: `/FOCUS/metadata` -* focus data location: `/FOCUS/data` - -!INCLUDE "data_generator_example.md",1 -!INCLUDE "schema_metadata_example.md",1 -!INCLUDE "schema_metadata_reference_example.md",1 -!INCLUDE "adding_new_columns_example.md",1 -!INCLUDE "removing_columns_example.md",1 -!INCLUDE "changing_a_columns_metadata_example.md", -!INCLUDE "correcting_schema_error_example.md",1 -!INCLUDE "focus_version_changed_example.md",1 -!INCLUDE "focus_version_changed_with_provider_version_example.md",1 -!INCLUDE "provider_version_changed.md",1 diff --git a/specification/appendix/examples/metadata/adding_new_columns_example.md b/specification/appendix/examples/metadata_examples/adding_new_columns_example.md similarity index 80% rename from specification/appendix/examples/metadata/adding_new_columns_example.md rename to specification/appendix/examples/metadata_examples/adding_new_columns_example.md index ede72f5c8..fb3111dec 100644 --- a/specification/appendix/examples/metadata/adding_new_columns_example.md +++ b/specification/appendix/examples/metadata_examples/adding_new_columns_example.md @@ -2,15 +2,13 @@ ## Scenario -ACME has decided add additional columns to their FOCUS data export. The new columns are x_awesome_column1, x_awesome_column2, and x_awesome_column3. The provider creates a new schema object to represent the new schema, this schema object has a unique SchemaId. The subsequent data exports that use the new schema include the new schema's id as a reference to their corresponding schema object. +ACME has decided add additional columns to their FOCUS data export. The new columns are x_awesome_column1, x_awesome_column2, and x_awesome_column3. The provider creates a new [Schema](#schema) object to represent the new schema, this schema object has a unique [SchemaId](#schemaid). The subsequent data exports that use the new schema include the new schema's id as a reference to their corresponding schema object. ## Supplied Metadata -## Location for the new schema object +Metadata can be provided at a location such as `/FOCUS/metadata/schemas/schema-23456-abcde-23456-abcde-23456.json`. -`/FOCUS/metadata/schemas/schema-23456-abcde-23456-abcde-23456.json` - -## Content for the new schema object +The updated schema related metadata could look like this: ```json { @@ -75,4 +73,4 @@ ACME has decided add additional columns to their FOCUS data export. The new colu } ``` -For an example of how ACME ensures the schema metadata reference requirement is met see: [Schema Metadata to FOCUS Data Reference](../schema_metadata_reference_example.md) +For an example of how ACME ensures the schema metadata reference requirement is met see: [Schema Metadata to FOCUS Data Reference](#schemametadatatofocusdatareference) diff --git a/specification/appendix/examples/metadata/changing_column_metadata_example.md b/specification/appendix/examples/metadata_examples/changing_column_metadata_example.md similarity index 83% rename from specification/appendix/examples/metadata/changing_column_metadata_example.md rename to specification/appendix/examples/metadata_examples/changing_column_metadata_example.md index 85d65e9f9..7e2bb1687 100644 --- a/specification/appendix/examples/metadata/changing_column_metadata_example.md +++ b/specification/appendix/examples/metadata_examples/changing_column_metadata_example.md @@ -1,16 +1,14 @@ -# Changing a Column's Metadata Example +# Changing Column Metadata ## Scenario -ACME has decided to change the datatype of column x_awesome_column1 from a string to a number. ACME creates a new schema object with the modification to x_awesome_column2. +ACME has decided to change the datatype of column x_awesome_column1 from a string to a number. ACME creates a new [Schema](#schema) object with the modification to x_awesome_column2. ## Supplied Metadata -## Location for the new schema object +Metadata can be provided at a location such as `/FOCUS/metadata/schemas/schema-67891-abcde-67891-abcde-67891.json`. -`/FOCUS/metadata/schemas/schema-67891-abcde-67891-abcde-67891.json` - -## Content for the new schema object +The updated schema related metadata could look like this: ```json { @@ -69,4 +67,4 @@ ACME has decided to change the datatype of column x_awesome_column1 from a strin } ``` -For an example of how ACME ensures the schema metadata reference requirement is met see: [Schema Metadata to FOCUS Data Reference](schema_metadata_reference_example.md) +For an example of how ACME ensures the schema metadata reference requirement is met see: [Schema Metadata to FOCUS Data Reference](#schemametadatatofocusdatareference) diff --git a/specification/appendix/examples/metadata/correcting_schema_errors_example.md b/specification/appendix/examples/metadata_examples/correcting_schema_errors_example.md similarity index 79% rename from specification/appendix/examples/metadata/correcting_schema_errors_example.md rename to specification/appendix/examples/metadata_examples/correcting_schema_errors_example.md index 16d166c3b..1248e7c24 100644 --- a/specification/appendix/examples/metadata/correcting_schema_errors_example.md +++ b/specification/appendix/examples/metadata_examples/correcting_schema_errors_example.md @@ -1,16 +1,14 @@ -# Provider has an error in their schema metadata +# Provider Metadata Error Correction ## Scenario -ACME has discovered that while their export includes the column x_awesome_column3, the schema metadata does not include this column. In this case, the provider fixes the metadata in existing the schema object and does not need to create a new schema object. Reference metadata remains the same. +ACME has discovered that while their export includes the column x_awesome_column3, the [Schema](#schema) metadata does not include this column. In this case, the provider fixes the metadata in the existing schema object and does not need to create a new schema object. Reference metadata remains the same. ## Supplied Metadata -## Location of the schema object +Metadata can be provided at a location such as `/FOCUS/metadata/schemas/schema-34567-abcde-34567-abcde-34567.json`. -`/FOCUS/metadata/schemas/schema-34567-abcde-34567-abcde-34567.json` - -## Content of the schema object +The updated schema related metadata could look like this: ```json { @@ -70,3 +68,4 @@ ACME has discovered that while their export includes the column x_awesome_column ] } ``` + diff --git a/specification/appendix/examples/metadata_examples/data_generator_example.md b/specification/appendix/examples/metadata_examples/data_generator_example.md new file mode 100644 index 000000000..62f03e9e3 --- /dev/null +++ b/specification/appendix/examples/metadata_examples/data_generator_example.md @@ -0,0 +1,18 @@ +# Data Generator Metadata + +## Scenario + +Acme provides metadata about the data generator as a part of their FOCUS data export. They provide the relevant data via the [Data Generator](#datagenerator) schema object. + +## Supplied Metadata + +Metadata can be provided at a location such as `/FOCUS/metadata/data_generator.json`. + +The updated data generator related metadata could look like this: + +```json +{ + "DataGenerator": "Acme" +} +``` + diff --git a/specification/appendix/examples/metadata/focus_version_changed_example.md b/specification/appendix/examples/metadata_examples/focus_version_changed_example.md similarity index 71% rename from specification/appendix/examples/metadata/focus_version_changed_example.md rename to specification/appendix/examples/metadata_examples/focus_version_changed_example.md index 31a28b8ce..d684e31e6 100644 --- a/specification/appendix/examples/metadata/focus_version_changed_example.md +++ b/specification/appendix/examples/metadata_examples/focus_version_changed_example.md @@ -1,16 +1,14 @@ -# Provider has an error in their schema metadata +# FOCUS Version Changed ## Scenario -ACME's previous exports used Focus Version 1.0. They are now going to adopt Focus Version 1.1. It is required that they create a new schema metadata object when using a new FOCUS version regardless of schema changes. In this example, the FOCUS new version adoption doesn't include columns changes. This is to illustrate that FOCUS Version changes are independent of column changes, however, this scenario is unlikely. +ACME's previous exports used FOCUS version 1.0. They are now going to adopt FOCUS version 1.1. It is required that they create a new schema metadata object which specifies the new FOCUS version via the [FOCUS Version](#focusversion) property - regardless of schema changes. In this example, the new FOCUS version adoption doesn't include columns changes. This is to illustrate that FOCUS version changes are independent of column changes, however, this scenario is unlikely. ## Supplied Metadata -## Location of the new schema object +Metadata can be provided at a location such as `/FOCUS/metadata/schemas/schema-45678-abcde-45678-abcde-45678.json`. -`/FOCUS/metadata/schemas/schema-45678-abcde-45678-abcde-45678.json` - -## Content of the schema object +The updated schema related metadata could look like this: ```json { @@ -69,4 +67,4 @@ ACME's previous exports used Focus Version 1.0. They are now going to adopt Focu } ``` -For an example of how ACME ensures the schema metadata reference requirement is met see: [Schema Metadata to FOCUS Data Reference](schema_metadata_reference_example.md) +For an example of how ACME ensures the schema metadata reference requirement is met see: [Schema Metadata to FOCUS Data Reference](#schemametadatatofocusdatareference) diff --git a/specification/appendix/examples/metadata/focus_version_changed_with_provider_version_used_example.md b/specification/appendix/examples/metadata_examples/focus_version_changed_with_provider_version_used_example.md similarity index 80% rename from specification/appendix/examples/metadata/focus_version_changed_with_provider_version_used_example.md rename to specification/appendix/examples/metadata_examples/focus_version_changed_with_provider_version_used_example.md index bf166cfa3..536a4a1b0 100644 --- a/specification/appendix/examples/metadata/focus_version_changed_with_provider_version_used_example.md +++ b/specification/appendix/examples/metadata_examples/focus_version_changed_with_provider_version_used_example.md @@ -2,23 +2,22 @@ ## Scenario -ACME uses Provider Version, and their previous exports used FOCUS Version 1.0. Their current Provider Version is 2.2. They are now going to adopt FOCUS Version 1.1. Because it is required that they update their Provider Version when using a new FOCUS Version, they create a new schema object designating that both have changed. In this example, the adoption of the new FOCUS Version doesn't include additional columns. This is to illustrate that Provider Version changes are independent of column changes; however, this scenario is unlikely. +ACME specifies the optional metadata property [Provider Version](#providerversion) in their [Schema](#schema) object. Their provider version 2.2 supported FOCUS version 1.0. They are now going to adopt FOCUS Version 1.1 which requires that they update their Provider Version when updating the FOCUS Version. They create a new schema object designating that both properties have changed. In this example, the adoption of the new FOCUS version doesn't include additional columns. This is to illustrate that Provider Version can change independent of column changes; however, this scenario is unlikely. The provider creates a new schema object to represent the new schema. The provider includes both the new FOCUS Version and Provider Version in the schema object. ## Supplied Metadata -## Location of the previous schema object +Metadata can be provided at a location such as `/FOCUS/metadata/schemas/schema-45678-abcde-45678-abcde-45678.json`. -`/FOCUS/metadata/schemas/schema-34567-abcde-34567-abcde-34567.json` - -## Content of the previous schema object +The updated schema related metadata could look like this: ```json { - "SchemaId": "34567-abcde-34567-abcde-34567", + "SchemaId": "45678-abcde-45678-abcde-45678", "FocusVersion": "1.1", - "ProviderVersion": "2.2", + "ProviderVersion": "2.3", + "name": "New Columns", "CreationDate": "2024-04-02T12:01:03.083z", "ColumnDefinition": [ { @@ -72,18 +71,13 @@ The provider creates a new schema object to represent the new schema. The provid } ``` -## Location of the new schema object - -`/FOCUS/metadata/schemas/schema-45678-abcde-45678-abcde-45678.json` - -## Content of the new schema object +For reference, the prior schema object looked like this: ```json { - "SchemaId": "45678-abcde-45678-abcde-45678", - "FocusVersion": "1.1", - "ProviderVersion": "2.3", - "name": "New Columns", + "SchemaId": "34567-abcde-34567-abcde-34567", + "FocusVersion": "1.0", + "ProviderVersion": "2.2", "CreationDate": "2024-04-02T12:01:03.083z", "ColumnDefinition": [ { @@ -137,4 +131,4 @@ The provider creates a new schema object to represent the new schema. The provid } ``` -For an example of how ACME ensures the schema metadata reference requirement is met see: [Schema Metadata to FOCUS Data Reference](schema_metadata_reference_example.md) +For an example of how ACME ensures the schema metadata reference requirement is met see: [Schema Metadata to FOCUS Data Reference](#schemametadatatofocusdatareference) diff --git a/specification/appendix/examples/metadata_examples/metadata_examples.mdpp b/specification/appendix/examples/metadata_examples/metadata_examples.mdpp new file mode 100644 index 000000000..eae6ee5f2 --- /dev/null +++ b/specification/appendix/examples/metadata_examples/metadata_examples.mdpp @@ -0,0 +1,24 @@ +# Metadata Examples + +The following sections contain examples of metadata provided by a hypothetical FOCUS data provider called ACME to supply the required reference between the FOCUS dataset and the schema metadata. Provider implementations will vary on how the metadata is disseminated; however, the provider's chosen metadata delivery approach should be able to support the structure represented in this example. + +In this example, the provider supports delivery of FOCUS data via file export to a data storage system. It uses JSON as the format for providing the metadata. The provider delivers data every 12 hours into a path structure described below: + +| Type of data | Path | +|:--------------------|:------------------| +| Export location | `/FOCUS` | +| Metadata location | `/FOCUS/metadata` | +| Cost data location | `/FOCUS/data` | + +Here are some metadata examples for various scenarios: + +!INCLUDE "data_generator_example.md",1 +!INCLUDE "schema_metadata_example.md",1 +!INCLUDE "schema_metadata_reference_example.md",1 +!INCLUDE "adding_new_columns_example.md",1 +!INCLUDE "removing_columns_example.md",1 +!INCLUDE "changing_column_metadata_example.md",1 +!INCLUDE "correcting_schema_errors_example.md",1 +!INCLUDE "focus_version_changed_example.md",1 +!INCLUDE "focus_version_changed_with_provider_version_used_example.md",1 +!INCLUDE "provider_version_changed_example.md",1 diff --git a/specification/appendix/examples/metadata/provider_version_changed_example.md b/specification/appendix/examples/metadata_examples/provider_version_changed_example.md similarity index 69% rename from specification/appendix/examples/metadata/provider_version_changed_example.md rename to specification/appendix/examples/metadata_examples/provider_version_changed_example.md index 530e56ca7..ed912bacf 100644 --- a/specification/appendix/examples/metadata/provider_version_changed_example.md +++ b/specification/appendix/examples/metadata_examples/provider_version_changed_example.md @@ -1,19 +1,16 @@ -# FOCUS Version Changed by Provider Using Provider Version +# Data Changed by Provider Using Provider Version ## Scenario -ACME uses provider version, and they made a change to their approach to create FOCUS data that does not adopt a new FOCUS Version, nor make a change the included columns but does impact values in the data. This is to illustrate that Provider Version changes are independent of column changes, however provider version changes may include column changes. +ACME specifies the optional metadata property [Provider Version](#providerversion) in their [Schema](#schema) object. They made a change to the FOCUS dataset they produce that does not adopt a new FOCUS Version, nor make a change the included columns but does impact values in the data. This example illustrates that Provider Version changes are independent of column changes, however provider version changes may include column changes. -The provider creates a new schema object to represent the new schema. The provider includes both the new FOCUS Version and Provider Version in the schema object. +The provider creates a new schema object to represent the new schema. The provider includes both the FOCUS Version and Provider Version in the schema object. ## Supplied Metadata -## Location of the new schema object +Metadata can be provided at a location such as `/FOCUS/metadata/schemas/schema-56789-abcde-56789-abcde-56789.json`. - -`/FOCUS/metadata/schemas/schema-56789-abcde-56789-abcde-56789.json` - -## Content of the new schema object +The updated schema related metadata could look like this: ```json { @@ -73,4 +70,4 @@ The provider creates a new schema object to represent the new schema. The provid } ``` -For an example of how ACME ensures the schema metadata reference requirement is met see: [Schema Metadata to FOCUS Data Reference](schema_metadata_reference_example.md) +For an example of how ACME ensures the schema metadata reference requirement is met see: [Schema Metadata to FOCUS Data Reference](#schemametadatatofocusdatareference) diff --git a/specification/appendix/examples/metadata/removing_columns_example.md b/specification/appendix/examples/metadata_examples/removing_columns_example.md similarity index 86% rename from specification/appendix/examples/metadata/removing_columns_example.md rename to specification/appendix/examples/metadata_examples/removing_columns_example.md index b9f47e31e..0b44141cd 100644 --- a/specification/appendix/examples/metadata/removing_columns_example.md +++ b/specification/appendix/examples/metadata_examples/removing_columns_example.md @@ -2,15 +2,13 @@ ## Scenario -ACME has decided to remove columns from their FOCUS data export. The column removed is x_awesome_column3. The provider creates a new schema object to represent the new schema, this schema object has a unique SchemaId. +ACME has decided to remove columns from their FOCUS data export. The column removed is x_awesome_column3. The provider creates a new [Schema](#schema) object to represent the new schema, with a unique [SchemaId](#schemaid). ## Supplied Metadata -## Location for the new schema object +Metadata can be provided at a location such as `/FOCUS/metadata/schemas/schema-34567-abcde-34567-abcde-34567.json`. -`/FOCUS/metadata/schemas/schema-34567-abcde-34567-abcde-34567.json` - -## Content for the new schema object +The updated schema related metadata could look like this: ```json { @@ -69,4 +67,4 @@ ACME has decided to remove columns from their FOCUS data export. The column remo } ``` -For an example of how ACME ensures the schema metadata reference requirement is met see: [Schema Metadata to FOCUS Data Reference](schema_metadata_reference_example.md) +For an example of how ACME ensures the schema metadata reference requirement is met see: [Schema Metadata to FOCUS Data Reference](#schemametadatatofocusdatareference) diff --git a/specification/appendix/examples/metadata/schema_metadata_example.md b/specification/appendix/examples/metadata_examples/schema_metadata_example.md similarity index 76% rename from specification/appendix/examples/metadata/schema_metadata_example.md rename to specification/appendix/examples/metadata_examples/schema_metadata_example.md index 6a52bda73..8ec30f88e 100644 --- a/specification/appendix/examples/metadata/schema_metadata_example.md +++ b/specification/appendix/examples/metadata_examples/schema_metadata_example.md @@ -1,16 +1,14 @@ -# Schema Metadata Example +# Schema Metadata ## Scenario -ACME has only provided one schema for their provided FOCUS data. ACME provides a directory of schemas and each schema is a single file. Acme's provides a file representing the schema for the data they provide. +ACME has only provided one [Schema](#schema) for their FOCUS data export. ACME provides a directory of schemas and each schema is a single file. Acme's provides a file representing the schema for the data they provide. ## Supplied Metadata -## Location of the schema object +Metadata can be provided at a location such as `/FOCUS/metadata/schemas/schema-1234-abcde-12345-abcde-12345.json`. -`/FOCUS/metadata/schemas/schema-1234-abcde-12345-abcde-12345.json` - -## Content of the schema object +The updated schema related metadata could look like this: ```json { diff --git a/specification/appendix/examples/metadata/schema_metadata_reference_example.md b/specification/appendix/examples/metadata_examples/schema_metadata_reference_example.md similarity index 63% rename from specification/appendix/examples/metadata/schema_metadata_reference_example.md rename to specification/appendix/examples/metadata_examples/schema_metadata_reference_example.md index 9edab82c1..d2ac2aa3b 100644 --- a/specification/appendix/examples/metadata/schema_metadata_reference_example.md +++ b/specification/appendix/examples/metadata_examples/schema_metadata_reference_example.md @@ -2,15 +2,13 @@ ## Scenario -ACME makes a change to the schema of their data exports. For each FOCUS data export, ACME includes a metadata reference to the schema object. Because multiple files are provided, Acme has elected to include a metadata file that includes the focus schema reference that applies to the data export files. They therefore include the new schema id in their export metadata file. +ACME makes a change to the [Schema](#schema) of their data exports. For each FOCUS data export, ACME includes a metadata reference to the schema object. Because multiple files are provided in each export, Acme has elected to include a metadata file in each export folder that includes the FOCUS schema reference that applies to the data export files within that folder. When the schema changes, they include the new [Schema ID](#schemaid) in their export metadata file of the new folder. ## Supplied Metadata -## Location of the existing schema metadata reference file +Metadata can be provided at a location such as `/FOCUS/data/export1-metadata.json` -`/FOCUS/data/export1-metadata.json` - -## Content for the existing export metadata object +The export metadata could look like this: ```json { @@ -41,11 +39,9 @@ ACME makes a change to the schema of their data exports. For each FOCUS data exp } ``` -## Location for the new export metadata object - -`/FOCUS/data/export2-metadata.json` +New metadata can be provided at a location such as `/FOCUS/data/export2-metadata.json`. -## Content for the new export metadata object +The new export metadata could look like this: ```json { diff --git a/specification/metadata/data_generator/data_generator.mdpp b/specification/metadata/data_generator/data_generator.mdpp index 2526c9bc2..f6381353c 100644 --- a/specification/metadata/data_generator/data_generator.mdpp +++ b/specification/metadata/data_generator/data_generator.mdpp @@ -8,6 +8,6 @@ The FOCUS Data Generator metadata MUST be provided. This metadata MUST be of typ ## Schema Example -For an example of the FOCUS Data Generator metadata please refer to: [Data Generator Example](#data_generator_example) +For an example of the FOCUS Data Generator metadata please refer to: [Data Generator Example](#datageneratormetadata) !INCLUDE "datagenerator.md",1 diff --git a/specification/metadata/schema/schema.mdpp b/specification/metadata/schema/schema.mdpp index 7d211016c..50825a4fe 100644 --- a/specification/metadata/schema/schema.mdpp +++ b/specification/metadata/schema/schema.mdpp @@ -15,13 +15,12 @@ It is recommended that the schema reference be provided as an external reference Should the provider change the structure of the supplied FOCUS data artifact, a new schema metadata object MUST be supplied. These scenarios include, but are not limited to: -* [Adding a new column](#adding_new_columns_example) -* [Removing a column](#removing_columns_example) -* [Renaming a column](#renaming_columns_example) -* [Changing column metadata](#changing_column_metadata_example) -* [FOCUS Version is changed](#focus_version_change_example) -* [Provider Version is changed](#provider_version_change_example) -* [Correcting schema metadata errors](#correcting_schema_metadata_errors) +* [Adding a new column](#addingnewcolumns) +* [Removing a column](#removingcolumns) +* [Changing column metadata](#changingcolumnmetadata) +* [FOCUS Version has changed](#focusversionchanged) +* [Provider Version has changed](#schemametadatatofocusdatareference) +* [Correcting schema metadata errors](#providermetadataerrorcorrection) ### Schema Metadata Updates @@ -29,10 +28,10 @@ Should there be an error where the schema metadata object does not match the sch ## Schema Example -For an example of the FOCUS schema metadata please refer to: [Schema Metadata Example](#schema-metadata-examples) +For an example of the FOCUS schema metadata please refer to: [Schema Metadata Example](#schemametadata) !INCLUDE "schemaid.md",1 !INCLUDE "creationdate.md",1 !INCLUDE "focusversion.md",1 -!INCLUDE "providerversion.md", +!INCLUDE "providerversion.md",1 !INCLUDE "column_definition/column_definition.mdpp",1 From 6660a240483e3061f5a19f07fa1db71ab614c89f Mon Sep 17 00:00:00 2001 From: Irena Jurica Date: Fri, 4 Oct 2024 01:42:09 +0200 Subject: [PATCH 02/22] FOCUS #547: Consistency Review - Standardize column specs for correction charges (#549) Standardize the column specifications, i.e. allow nulls in the case of corrections for all columns except cost metrics, and explicitly define value ranges for all metrics, for the following columns: - PricingUnit - ConsumedUnit - CommitmentDiscountUnit - PricingQuantity - ConsumedQuantity - CommitmentDiscountQuantity - ListCost - ContractedCost - ListUnitPrice - ContractedUnitPrice --- ### NOTE: An initial overall analysis of the current correction handling and value ranges was conducted within this PR. Due to deadlines, **the scope of this particular PR was limited to addressing the following two columns**: - **ConsumedUnit** - **ConsumedQuantity** Please use this [table](https://docs.google.com/spreadsheets/d/1SvaD-PSzxwRKExKYbQXbtEmVPtbhN4HnycOatvLfGPI/edit?gid=1823426118#gid=1823426118) to verify the normative requirements. --------- Co-authored-by: Joaquin --- specification/columns/consumedquantity.md | 10 +++++----- specification/columns/consumedunit.md | 10 +++++----- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/specification/columns/consumedquantity.md b/specification/columns/consumedquantity.md index b7ea4d2d8..b29caa225 100644 --- a/specification/columns/consumedquantity.md +++ b/specification/columns/consumedquantity.md @@ -1,14 +1,14 @@ # Consumed Quantity -The Consumed Quantity represents the volume of a given SKU associated with a metered [*resource*](#glossary:resource) or [*service*](#glossary:service) used, based on the [Consumed Unit](#consumedunit). Consumed Quantity is often derived at a finer granularity or over a different time interval when compared to the [Pricing Quantity](#pricingquantity) (complementary to [Pricing Unit](#pricingunit)) and focuses on metered *resource* and *service* consumption, not pricing and cost. +The Consumed Quantity represents the volume of a metered SKU associated with a [*resource*](#glossary:resource) or [*service*](#glossary:service) used, based on the [Consumed Unit](#consumedunit). Consumed Quantity is often derived at a finer granularity or over a different time interval when compared to the [Pricing Quantity](#pricingquantity) (complementary to [Pricing Unit](#pricingunit)) and focuses on *resource* and *service* consumption, not pricing and cost. The ConsumedQuantity column adheres to the following requirements: * ConsumedQuantity MUST be present in a FOCUS dataset when the provider supports the measurement of usage. * ConsumedQuantity MUST be of type Decimal and MUST conform to [Numeric Format](#numericformat) requirements. -* ConsumedQuantity MUST NOT be null if [ChargeCategory](#chargecategory) is "Usage" and [ChargeClass](#chargeclass) is not "Correction". -* ConsumedQuantity MUST be null if [CommitmentDiscountStatus](#commitmentdiscountstatus) is "Unused" or for other *ChargeCategory* values. -* ConsumedQuantity MAY be negative or null in cases where *ChargeClass* is "Correction". +* ConsumedQuantity MUST NOT be null and MUST be a valid positive decimal value if [ChargeCategory](#chargecategory) is "Usage", [CommitmentDiscountStatus](#commitmentdiscountstatus) is not "Unused", and [ChargeClass](#chargeclass) is not "Correction". +* ConsumedQuantity MAY be null or any valid decimal value if ChargeCategory is "Usage", CommitmentDiscountStatus is not "Unused", and ChargeClass is "Correction". +* ConsumedQuantity MUST be null in all other cases. ## Column ID @@ -20,7 +20,7 @@ Consumed Quantity ## Description -The volume of a given SKU associated with a metered *resource* or *service* used, based on the Consumed Unit. +The volume of a metered SKU associated with a *resource* or *service* used, based on the Consumed Unit. ## Content constraints diff --git a/specification/columns/consumedunit.md b/specification/columns/consumedunit.md index 7fcb4a37a..36d2760f6 100644 --- a/specification/columns/consumedunit.md +++ b/specification/columns/consumedunit.md @@ -1,14 +1,14 @@ # Consumed Unit -The Consumed Unit represents a provider-specified measurement unit indicating how a provider measures usage of a given SKU associated with a metered [*resource*](#glossary:resource) or [*service*](#glossary:service). Consumed Unit complements the [Consumed Quantity](#consumedquantity) metric. It is often listed at a finer granularity or over a different time interval when compared to [Pricing Unit](#pricingunit) (complementary to [Pricing Quantity](#pricingquantity)), and focuses on metered *resource* and *service* consumption, not pricing and cost. +The Consumed Unit represents a provider-specified measurement unit indicating how a provider measures usage of a metered SKU associated with a [*resource*](#glossary:resource) or [*service*](#glossary:service). Consumed Unit complements the [Consumed Quantity](#consumedquantity) metric. It is often listed at a finer granularity or over a different time interval when compared to [Pricing Unit](#pricingunit) (complementary to [Pricing Quantity](#pricingquantity)), and focuses on *resource* and *service* consumption, not pricing and cost. The ConsumedUnit column adheres to the following requirements: * ConsumedUnit MUST be present in the billing data when the provider supports the measurement of usage. * ConsumedUnit MUST be of type String, and the units of measure used in ConsumedUnit SHOULD adhere to the values and format requirements specified in the [UnitFormat](#unitformat) attribute. -* ConsumedUnit MUST NOT be null if [ChargeCategory](#chargecategory) is "Usage" and [ChargeClass](#chargeclass) is not "Correction". -* When *ChargeCategory* is not "Usage", or *ChargeCategory* is "Usage" and [CommitmentDiscountStatus](#commitmentdiscountstatus) is "Unused", ConsumedUnit MUST be null when ChargeClass is not "Correction". -* ConsumedUnit MAY be null if *ChargeCategory* is "Usage" and ChargeClass is "Correction". +* ConsumedUnit MUST NOT be null if [ChargeCategory](#chargecategory) is "Usage", [CommitmentDiscountStatus](#commitmentdiscountstatus) is not "Unused", and [ChargeClass](#chargeclass) is not "Correction". +* ConsumedUnit MAY be null if ChargeCategory is "Usage", CommitmentDiscountStatus is not "Unused", and ChargeClass is "Correction". +* ConsumedUnit MUST be null in all other cases. ## Column ID @@ -20,7 +20,7 @@ Consumed Unit ## Description -Provider-specified measurement unit indicating how a provider measures usage of a given SKU associated with a metered *resource* or *service*. +Provider-specified measurement unit indicating how a provider measures usage of a metered SKU associated with a *resource* or *service*. ## Content constraints From ca924c8c5ed6fcbf7838e0ae7ac005e56662f26c Mon Sep 17 00:00:00 2001 From: Udam Dewaraja Date: Thu, 3 Oct 2024 16:46:37 -0700 Subject: [PATCH 03/22] Service Subcategory language inconsistency fixes (#552) Fixes based on discussions at the consistency review meeting on 9/25. --------- Co-authored-by: Joaquin --- specification/columns/servicesubcategory.md | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/specification/columns/servicesubcategory.md b/specification/columns/servicesubcategory.md index 82548de45..c353d039f 100644 --- a/specification/columns/servicesubcategory.md +++ b/specification/columns/servicesubcategory.md @@ -2,10 +2,12 @@ The Service Subcategory is a secondary classification of the Service Category for a [*service*](#glossary:service) based on its core function. The Service Subcategory (in conjunction with the Service Category) is commonly used for scenarios like analyzing spend and usage for specific workload types across providers and tracking the migration of workloads across fundamentally different architectures. -* The ServiceSubcategory column MUST be present in a FOCUS dataset and MUST NOT be null. -* This column is of type String and MUST be one of the allowed values. -* Each Service Subcategory value MUST have one and only one Service Category parent. -* Though a given *service* can have multiple purposes, each *service* SHOULD have one and only one Subcategory that best aligns with its primary purpose. +The ServiceSubcategory column adheres to the following requirements: + +* ServiceSubcategory is RECOMMENDED to be present in a FOCUS dataset and MUST NOT be null. +* ServiceSubcategory is of type String and MUST be one of the allowed values. +* Each ServiceSubcategory value MUST have one and only one parent ServiceCategory as specified in the allowed values below. +* Though a given *service* can have multiple purposes, each *service* SHOULD have one and only one ServiceSubcategory that best aligns with its primary purpose. ## Column ID @@ -24,7 +26,7 @@ Secondary classification of the Service Category for a *service* based on its co | Constraint | Value | | :-------------- | :------------- | | Column type | Dimension | -| Feature level | Optional | +| Feature level | Recommended | | Allows nulls | False | | Data type | String | | Value format | Allowed Values | From 77496775c5e1033b34fc6c7fdb4ef8c6252adac9 Mon Sep 17 00:00:00 2001 From: Christopher Harris Date: Thu, 3 Oct 2024 19:58:24 -0400 Subject: [PATCH 04/22] [EDITORIAL - Alternate version] Mark commitment discount purchase's pricing_category as "Standard" (#579) Co-authored-by: AWS-ZachErdman --- specification/appendix/commitment_discounts.md | 10 +++++----- specification/columns/pricingcategory.md | 4 ++-- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/specification/appendix/commitment_discounts.md b/specification/appendix/commitment_discounts.md index 6f83a618f..ed4733c68 100644 --- a/specification/appendix/commitment_discounts.md +++ b/specification/appendix/commitment_discounts.md @@ -31,7 +31,7 @@ Within the FOCUS specification, the following examples demonstrate how a *commit ### Purchase *Rows* -All *commitment discount* purchases appear with a positive `BilledCost`, `PricingCategory` as "Committed", and with the *commitment discount's* id populating both the `ResourceId` and `CommitmentDiscountId` value. One-time purchases appear as a single record with `ChargeCategory` as "Purchase", `ChargeFrequency` as "One-Time", and the total quantity and units for *commitment discount's* *term* reflected as `CommitmentDiscountQuantity` and `CommitmentDiscountUnit`, respectively. +All *commitment discount* purchases appear with a positive `BilledCost`, `PricingCategory` as "Standard", and with the *commitment discount's* id populating both the `ResourceId` and `CommitmentDiscountId` value. One-time purchases appear as a single record with `ChargeCategory` as "Purchase", `ChargeFrequency` as "One-Time", and the total quantity and units for *commitment discount's* *term* reflected as `CommitmentDiscountQuantity` and `CommitmentDiscountUnit`, respectively. Recurring purchases are allocated across all corresponding *charge periods* of the *term* when `ChargeCategory` is "Purchase", `ChargeFrequency` is "Recurring", and `CommitmentDiscountQuantity` and `CommitmentDiscountUnit` are reflected only for that *charge period*. @@ -50,7 +50,7 @@ The entire *commitment discount* is billed _once_ during the first *charge perio "ChargePeriodEndDate": "2024-01-01T00:00:00Z", "ChargeCategory": "Purchase", "ChargeFrequency": "One-Time", - "PricingCategory": "Committed", + "PricingCategory": "Standard", "ResourceId": "", "BilledCost": 8760.00, "EffectiveCost": 0.00, @@ -74,7 +74,7 @@ The *commitment discount* is billed across all 8,760 (`24 hours * 365 days`) *ch "ChargePeriodEndDate": "2023-01-01T01:00:00Z", "ChargeCategory": "Purchase", "ChargeFrequency": "Recurring", - "PricingCategory": "Committed", + "PricingCategory": "Standard", "ResourceId": "", "BilledCost": 1.00, "EffectiveCost": 0.00, @@ -100,7 +100,7 @@ With a 50/50 split, half of the commitment is billed _once_ during the first *ch "ChargePeriodEndDate": "2024-01-01T00:00:00Z", "ChargeCategory": "Purchase", "ChargeFrequency": "One-Time", - "PricingCategory": "Committed", + "PricingCategory": "Standard", "ResourceId": "", "BilledCost": 4380.00, "EffectiveCost": 0.00, @@ -115,7 +115,7 @@ With a 50/50 split, half of the commitment is billed _once_ during the first *ch "ChargePeriodEndDate": "2023-01-01T01:00:00Z", "ChargeCategory": "Purchase", "ChargeFrequency": "Recurring", - "PricingCategory": "Committed", + "PricingCategory": "Standard", "ResourceId": "", "BilledCost": 0.50, "EffectiveCost": 0.00, diff --git a/specification/columns/pricingcategory.md b/specification/columns/pricingcategory.md index 1636622d9..ae0369498 100644 --- a/specification/columns/pricingcategory.md +++ b/specification/columns/pricingcategory.md @@ -38,9 +38,9 @@ Allowed values: | Value | Description | | :-------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| Standard | Charges priced at the agreed upon rate for the billing account, including [*negotiated discounts*](#glossary:negotiated-discount). This includes any flat rate and volume/tiered pricing but does not include dynamic or *commitment discount* pricing. | +| Standard | Charges priced at the agreed upon rate for the billing account, including [*negotiated discounts*](#glossary:negotiated-discount). This pricing includes any flat rate and volume/tiered pricing but does not include dynamic pricing or reduced pricing due to the application of a *commitment discount*. This does include the purchase of a commitment discount at agreed upon rates. | | Dynamic | Charges priced at a variable rate determined by the provider. This includes any product or service with a unit price the provider can change without notice, like interruptible or low priority resources. | -| Committed | Charges with reduced prices due to a *commitment discount* specified by the Commitment Discount ID. | +| Committed | Charges with reduced pricing due to the application of the *commitment discount* specified by the Commitment Discount ID. | | Other | Charges priced in a way not covered by another pricing category. | ## Introduced (version) From 412eb24f02a85745b214e1ba4664c8b87bf5354e Mon Sep 17 00:00:00 2001 From: Christopher Harris Date: Thu, 3 Oct 2024 20:15:28 -0400 Subject: [PATCH 05/22] Adding 'Commitment Discount Visibility' to v1.1 Release Planning (#577) `Commitment Discount Visibility` --> Provide deeper visibility into how various commitment discount purchases are amortized across eligible resources. --- RELEASE-PLANNING.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/RELEASE-PLANNING.md b/RELEASE-PLANNING.md index 34b21361f..2063999ad 100644 --- a/RELEASE-PLANNING.md +++ b/RELEASE-PLANNING.md @@ -22,6 +22,10 @@ This section outlines the planned release schedule and key milestones for the FO
  • Move beyond the highest-level service categorization to a sub-categorization for services while adding flexibility for providers to share their native categorizations within FOCUS.
  • + Commitment Discount Visibility +
      +
    • Provide deeper visibility into how various commitment discount purchases are amortized across eligible resources.
    • +
    Capacity Reservation
    • Ability to represent on-demand capacity reservations within FOCUS datasets. From e34a65e9b8169ed629ae74d5c7b5e0f5b106dae2 Mon Sep 17 00:00:00 2001 From: Christopher Harris Date: Thu, 3 Oct 2024 20:31:16 -0400 Subject: [PATCH 06/22] Commitment Discount {Quantity,Unit} - Consistency review edits (#550) Adds correction-based logic and reduces duplication of clauses --------- Co-authored-by: Irena Jurica --- .../columns/commitmentdiscountquantity.md | 14 +++++++------- specification/columns/commitmentdiscountunit.md | 3 ++- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/specification/columns/commitmentdiscountquantity.md b/specification/columns/commitmentdiscountquantity.md index 79b096479..892b103f5 100644 --- a/specification/columns/commitmentdiscountquantity.md +++ b/specification/columns/commitmentdiscountquantity.md @@ -10,19 +10,19 @@ 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". +* CommitmentDiscountQuantity MAY be null or any valid decimal value if [*CommitmentDiscountId*](#commitmentdiscountid) is not null and [*ChargeClass*](#chargeclass) is "Correction". -In cases where the *ChargeCategory* is "Purchase" and [*CommitmentDiscountId*](#commitmentdiscountid) is not null, the following applies: +In cases where the *ChargeCategory* is "Purchase", *CommitmentDiscountId* is not null, and *ChargeClass* is not "Correction", 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: +In cases where the *ChargeCategory* is "Usage", *CommitmentDiscountId* is not null, and *ChargeClass* is not "Correction", 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*. +* When *CommitmentDiscountStatus* is "Used", CommitmentDiscountQuantity MUST be the positive, metered quantity of *CommitmentDiscountUnits* that is consumed over the *row's* *charge period*. +* When *CommitmentDiscountStatus* is "Unused", 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. +CommitmentDiscountQuantity MUST be null in all other cases. ## Column ID @@ -40,7 +40,7 @@ The amount of a *commitment discount* purchased or accounted for in *commitment | Constraint | Value | |:----------------|:-----------------| -| Column type | Dimension | +| Column type | Metric | | Feature level | Conditional | | Allows nulls | True | | Data type | Decimal | diff --git a/specification/columns/commitmentdiscountunit.md b/specification/columns/commitmentdiscountunit.md index 39c8784db..fc91838b1 100644 --- a/specification/columns/commitmentdiscountunit.md +++ b/specification/columns/commitmentdiscountunit.md @@ -7,7 +7,8 @@ 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 MAY be null if [*CommitmentDiscountId*](#commitmentdiscountid) is not null and [*ChargeClass*](#chargeclass) is "Correction". +* CommitmentDiscountUnit MUST NOT be null when *CommitmentDiscountId* is not null and *ChargeClass* is not "Correction". * CommitmentDiscountUnit MUST be null in all other cases. In cases where the CommitmentDiscountUnit is not null, the following applies: From 02a8df5802719c866814edd7e5a415bfc66705ff Mon Sep 17 00:00:00 2001 From: Joaquin Date: Thu, 3 Oct 2024 17:47:27 -0700 Subject: [PATCH 07/22] [EDITORIAL] Update the list of FOCUS release v1.1 contributors (#583) This pull request provides a draft list of FOCUS members who contributed to the FOCUS Release v1.1 specifications through various means, including submitting pull requests, reviewing existing submissions, or actively participating in discussions. --------- Co-authored-by: Karl <133434112+kk09v@users.noreply.github.com> Co-authored-by: Udam Dewaraja --- specification/contributors.md | 61 ++++++----------------------------- 1 file changed, 10 insertions(+), 51 deletions(-) diff --git a/specification/contributors.md b/specification/contributors.md index 2674fe1e6..8ecc94997 100644 --- a/specification/contributors.md +++ b/specification/contributors.md @@ -2,80 +2,39 @@ ### Maintainers -Thanks to the following FOCUS Maintainers for their leadership and contributions to the FOCUS specification. +Thanks to the following FOCUS Maintainers for their leadership and contributions to the FOCUS Release **v1.1** specification. +* Alex Hullah (Goldman Sachs) * Christopher Harris (Datadog) -* Dennis Park-Rodriguez (Amazon Web Services) -* Erik Peterson (CloudZero) * Irena Jurica (Neos) * Joaquin Prado (FinOps Foundation) * Karl Kraft (Walmart) * Larry Advey (Twilio) * Michael Flanakin (Microsoft) -* Mike Fuller (FinOps Foundation) * Riley Jenkins (Domo) -* Rupa Patel (Google) +* Shawn Alpay (Envisor / FinOps Foundation) * Udam Dewaraja (FinOps Foundation) +* Zach Erdman (Amazon Web Services) ### Contributors -Thanks to the following FOCUS members for their contributions to the FOCUS specification. +Thanks to the following FOCUS members for their contributions to the FOCUS Release **v1.1** specification. * Adam Schwartz (Ernst & Young) -* Alex Hullah (Goldman Sachs) -* Amit Wadhwa (Google) -* Anand Tripathi (Amazon Web Services) -* Anderson Oliveira (Farfetch.com) * Andrew Qu (Everest) -* Anne Johnston (Capital One) * Arun Ramakrishnan (Oracle) -* Ben Shy (Microsoft) -* Ben Swoboda (NetApp) -* Ben Zhou (Apptio) -* Casey Doran (Apptio) -* Chandra Devarajan (CloudTrakr) -* Chew Esmero (Alphaus Inc.) -* Colin Jack (Snow Software) -* Deeja Cruz (Datadog) -* Eleni Rundle (Google) +* Erik Peterson (CloudZero) * George Parker (Salesforce) * Graham Murphy (Australian Retirement Trust) -* Harish Kumar Munagapat (Kyndryl) -* Hrishikesh Sardar (Kyndryl) -* Ilia Semenov (CloudThread) -* Jacky Liu (Google Cloud) -* Jacqui Wilson (Old Mutual South Africa) * Janine Pickard-Green (MagicOrange Group Limited) -* Jason Kelly (Anglepoint Group Inc) -* Joe Ferrero (DB Gurus Inc) * John Grubb (Platform.sh) -* Joshua Kwan (Ternary) -* Letian Wang (Atlassian) -* Luna Bernal (Twilio) +* Joseph John (Microsoft) * Marc Perreaut (Amadeus) -* Marcin Walkow (Nordcloud) -* Mark Krawczeniuk (NetApp) -* Matt Ray (Kubecost) -* Michael Arkoosh (Vega) -* Mike Polson (VMWare) -* Nick Kotze (Surveil) -* Nicolas Fonrose (Teevity) -* Peter Marton (OpenMeter.io) -* Ray Ding (Accenture) -* Ricardo Triana (Accenture) -* Rodney Joyce (CloudMonitor) +* Rob Martin (FinOps Foundation) +* Rupa Patel (Google) * Sanjna Srivatsa (VMWare) -* Shawn Alpay (Envisor) -* Sireesha Oram (Kyndryl) * Sonal Garg (Kyndryl) -* Sumaira Nazir (Platform.sh) -* Tatiana Dubovchenko (Flexera) -* Tim O'Brien (Walmart) -* Trey Morgan (Microsoft) -* Trig Ghosh (Accenture) -* Webb Brown (Kubecost) -* Yuriy Prykhodko (Amazon Web Services) -* Zach Erdman (Amazon Web Services) +* Tim Wright (Google) ## Steering Committee Members From 44b86108da706b200de81e72d88a714b7985ef51 Mon Sep 17 00:00:00 2001 From: Udam Dewaraja Date: Fri, 4 Oct 2024 12:02:57 -0700 Subject: [PATCH 08/22] FOCUS-580: remove use case library and link to the FOCUS website (#581) --- specification/use_case_library.md | 45 +------------------------------ 1 file changed, 1 insertion(+), 44 deletions(-) diff --git a/specification/use_case_library.md b/specification/use_case_library.md index b8b5da96c..23069b781 100644 --- a/specification/use_case_library.md +++ b/specification/use_case_library.md @@ -1,46 +1,3 @@ # Use Case Library -The following table contains a set of commonly performed FinOps scenarios that were used as a basis for developing this specification. These use cases were developed by FinOps practitioners. - -| Persona | Capability | Use Case | FOCUS Columns | -|:--|:--|:--|:--| -| Business / Product Owner | Budget Management | As a Business/Product Owner, I need to compare actual usage costs incurred within a time period to the amount forecasted. | BilledCost
      BillingAccountId
      BillingAccountName
      ChargePeriodStart
      ChargePeriodEnd
      ChargeCategory
      Provider | -| Engineering & Operations | Budget Management | As an Engineering Manager who wants to reduce their billed cost for Compute for a specific provider, I want to understand what is my current rate of commitment discount (without negotiated discounts) per type of commitment, so that I can strategize further purchases | BillingPeriodStart
      CommitmentDiscountType
      EffectiveCost
      ProviderName
      ServiceName
      SubAccountId
      SubAccountName | -| Engineering & Operations | Data Analysis and Showback | As an Engineer, I want to understand the costs of the components that belong to an application | ChargeDescription
      ChargePeriodStart
      EffectiveCost
      ResourceId
      ResourceName
      ResourceType
      ServiceCategory
      ServiceName
      SkuId
      Tags | -| Engineering & Operations | Data Analysis and Showback | As an Engineer, I want to understand the costs of the components for a specific resource | ChargePeriodStart
      EffectiveCost
      ResourceId
      ResourceName
      SkuId | -| Engineering & Operations | Data Analysis and Showback | As an Engineer, I want to understand the costs of all components and resources within a subaccount | ChargePeriodStart
      EffectiveCost
      ResourceId
      ResourceName
      SkuId
      SubAccountId | -| Engineering & Operations | Data Analysis and Showback | As an Engineering & Operations person I would like to analyze the usage of serverless requests on a weekly basis to identity potential optimization candidates | BilledCost
      ProviderName
      ChargePeriodStart
      ChargePeriodEnd
      SkuId
      ConsumedQuantity
      Tags
      ConsumedUnit | -| Engineering & Operations | Data Analysis and Showback | As an Engineer, I need to extract a ranked list of the top 10 service cost drivers within a sub account from a time period | ChargePeriodStart
      EffectiveCost
      SubAccountId
      SubAccountName
      ServiceName | -| Engineering & Operations | Workload Management & Automation | As an Engineer I need to ensure my costs within a region are distributed across the different availability zones in an expected manner. | ProviderName
      AvailabilityZone
      RegionId
      RegionName
      BillingPeriodStart
      EffectiveCost | -| Engineering & Operations | Workload Management & Automation | As an Engineering manager, I need to see the cost of each compute resource in a production SubAccount I'm responsible for. | ResourceId
      ResourceName
      ChargePeriodStart
      ChargePeriodEnd
      ServiceName
      ServiceCategory
      PricingQuantity
      EffectiveCost | -| Finance | Budget Management | As a person in Finance, I need to update cloud budget with actual cost details within a billing period | BilledCost
      BillingPeriodStart
      BillingPeriodEnd
      ProviderName | -| Finance | Budget Management | As a person in Finance, I need to update budget, by application, with actual cost details within a billed time period | BilledCost
      BillingPeriodStart
      BillingPeriodEnd
      ProviderName
      Tags | -| Finance | Budget Management | As a person in Finance, I need to track tax costs month over month. | BillingPeriodStart
      BilledCost
      ChargeCategory
      ProviderName | -| Finance | Budget Management | As a Financial Analyst or member of the company's treasury, I would like to understand what volume of commitment discount charges are going to reoccur in the coming financial year | ChargeFrequency
      BillingPeriodStart
      BilledCost | -| Finance | Data Analysis and Showback | As a Finance person of a company that sells SaaS services, I need to determine the resource quantity and type used by a customer so that a monthly invoice can be issued to the customer. | ProviderName
      BillingPeriodStart
      SkuId
      PricingQuantity
      ConsumedQuantity
      ConsumedUnit
      Tags | -| Finance | Data Analysis and Showback | As a person in Finance, I need a report of all cost associated with a product from all geographic locations for a given month. | BilledCost
      BillingCurrency
      BillingAccountId
      BillingAccountName
      BillingPeriodEnd
      ProviderName
      Tags | -| Finance | FinOps & Intersecting Frameworks | As a person in Finance, I need a report of service-level cost within a specific Sub Account as a part of a private pricing negotiation. | BillingPeriodStart
      EffectiveCost
      ProviderName
      ServiceName
      SubAccountId
      SubAccountName | -| Finance | Forecasting | As a person in Finance, I need to forecast amortized costs on a month over month basis, based on historical trends | BillingPeriodStart
      ChargeCategory
      EffectiveCost
      PricingUnit
      ProviderName
      ServiceName
      ServiceCategory | -| Finance | Forecasting | As a person in Finance, I need to forecast cashflow on a month over month basis, based on historical trends | BillingPeriodStart
      ChargeCategory
      ChargeDescription
      BilledCost
      BillingCurrency
      ProviderName
      ServiceName
      ServiceCategory | -| FinOps Practitioner | Data Analysis and Showback | As a FinOps practitioner, I need to analyze service costs month over month, over a time period | EffectiveCost
      BillingPeriodStart
      ProviderName
      ServiceName | -| FinOps Practitioner | Data Analysis and Showback | As a FinOps practitioner, I need to analyze service costs, by region, over a time period | EffectiveCost
      BillingPeriodStart
      ProviderName
      RegionId
      RegionName
      ServiceName | -| FinOps Practitioner | Data Analysis and Showback | As a FinOps practitioner, I need to analyze Compute Engine service costs month over month for a period of time to identify accounts spending the most money on Compute Engine | BilledCost
      BillingPeriodStart
      ProviderName
      ResourceId
      ResourceName
      ServiceName
      SubAccountId
      SubAccountName | -| FinOps Practitioner | Data Analysis and Showback | As a FinOps practitioner, I want to monitor how much we are spending on a specific SaaS product purchased via the cloud service provider's marketplace. | ChargePeriodStart
      ChargePeriodEnd
      EffectiveCost
      InvoiceIssuer
      ProviderName
      Publisher | -| FinOps Practitioner | Data Analysis and Showback | As a FinOps Practitioner, I need to understand what we are spending across providers, billing periods, and service categories | ProviderName
      BillingPeriodStart
      BilledCost
      BillingCurrency
      ServiceCategory | -| FinOps Practitioner | FinOps & Intersecting Frameworks | As a FinOps Practitioner, I need to verify the accuracy of the cloud service provider invoices | ProviderName
      BillingAccountId
      BillingAccountName
      BillingPeriodStart
      BilledCost
      BillingCurrency | -| FinOps Practitioner | FinOps & Intersecting Frameworks | As a FinOps Practitioner, I need to verify the accuracy of the cloud service provider invoices and the underlying services | ProviderName
      BillingAccountId
      BillingAccountName
      BillingPeriodStart
      BilledCost
      BillingCurrency
      ServiceName | -| FinOps Practitioner | FinOps & Intersecting Frameworks | As a FinOps Practitioner, I need to reconcile discounts on the cloud service provider invoices and the underlying services | ProviderName
      BillingAccountId
      BillingAccountName
      BillingPeriodStart
      BilledCost
      BillingCurrency
      EffectiveCost
      ListCost
      ServiceName | -| FinOps Practitioner | FinOps & Intersecting Frameworks | As a FinOps Practitioner, I need to analyze usage data of resources | ChargePeriodStart
      ChargeCategory
      EffectiveCost
      ProviderName
      PricingQuantity
      ConsumedQuantity
      ResourceId
      ServiceName
      SkuId
      ConsumedUnit | -| FinOps Practitioner | Forecasting | As a FinOps Practitioner, I need to forecast costs, based on historical usage trends and rates | BillingPeriodStart
      ChargeCategory
      ChargeDescription
      EffectiveCost
      ProviderName
      PricingQuantity
      ConsumedQuantity
      RegionId
      ServiceCategory
      ServiceName
      SkuId
      ConsumedUnit | -| FinOps Practitioner | Managing Anomalies | As a FinOps Practitioner, I need to see the daily costs across all cloud providers, billing accounts, and sub accounts | BillingAccountId
      SubAccountId
      ChargePeriodStart
      ChargePeriodEnd
      ProviderName
      EffectiveCost | -| FinOps Practitioner | Managing Anomalies | As a FinOps Practitioner, I need to see the daily costs across all cloud providers, billing accounts, sub accounts, and region | BillingAccountId
      SubAccountId
      ChargePeriodStart
      ChargePeriodEnd
      EffectiveCost
      ProviderName
      RegionId
      RegionName | -| FinOps Practitioner | Managing Anomalies | As a FinOps practitioner, I need to see the daily costs across all cloud providers, billing accounts, sub accounts, and service | BillingAccountId
      SubAccountId
      ChargePeriodStart
      ChargePeriodEnd
      EffectiveCost
      ProviderName
      ServiceName | -| FinOps Practitioner | Managing Commitment Discounts | As a FinOps Practitioner, I want to track all commitment discounts purchased for a time period | ProviderName
      BillingAccountId
      CommitmentDiscountId
      CommitmentDiscountType
      BilledCost
      ChargePeriodStart
      ChargeCategory | -| FinOps Practitioner | Managing Commitment Discounts | As a FinOps Practitioner, I want to track unused commitment charges in any given time period so that I consider them in my future commitment planning or remedy them | CommitmentDiscountStatus (filter)
      CommitmentDiscountId
      BilledCost
      ChargePeriodStart | -| FinOps Practitioner | Resource Utilization & Efficiency | As a FinOps Practitioner, I need to analyze the fleet diversity in order to run a campaign to standardize application architecture. | ChargeCategory
      ChargeDescription
      ChargePeriodStart
      ProviderName
      ResourceType
      SubAccountId
      ServiceName | -| FinOps Practitioner | Resource Utilization & Efficiency | As a FinOps Practitioner, I need to analyze the fleet diversity in order to run a campaign to standardize application architecture within a specific service | ChargeCategory
      ChargeDescription
      ChargePeriodStart
      ProviderName
      ResourceType
      SubAccountId
      ServiceName | -| FinOps Practitioner | Resource Utilization & Efficiency | As a FinOps Practitioner, I need to identify total refunds within a billing period. | ProviderName
      BillingAccountId
      ServiceCategory
      BilledCost
      BillingPeriodStart
      ChargeCategory
      ChargeClass | -| FinOps Practitioner | Resource Utilization & Efficiency | As a FinOps Practitioner, I need to identify refunds across sub accounts within a billing period. | ProviderName
      BillingAccountId
      ServiceCategory
      BilledCost
      BillingPeriodStart
      ChargeCategory
      ChargeClass
      SubAccountId | -| FinOps Practitioner | Workload Management & Automation | As a FinOps Practitioner, I need to do an analysis on compliance to data residency requirements across all regions | ChargePeriodStart
      ProviderName
      RegionId
      RegionName
      SubAccountId | -| Procurement | Data Analysis and Showback | As a person in Procurement, I need to understand what we are spending, across billing periods, across service categories to focus negotiations toward highest costing items | ProviderName
      BillingAccountId
      BillingAccountName
      BillingCurrency
      BilledCost
      BillingPeriodStart
      ServiceCategory
      ServiceName | -| Procurement, Finance, FinOps Practitioner | FinOps & Intersecting Frameworks | Multiple personas in an organization need to know the top SKU Codes based on spend, so that they can achieve multiple goals such as contract negotiation, SKU based forecasting, or high unit cost cleanup activities. | ChargePeriodStart
      ChargePeriodEnd
      ListCost
      PricingUnit
      ListUnitPrice
      PricingQuantity
      SkuId
      SkuPriceId
      ProviderName | +This specification is based on a set of common FinOps use cases, which are publicly available at [https://focus.finops.org/use-cases/](https://focus.finops.org/use-cases/). Developed by FinOps practitioners, these use cases are organized by persona and capability, making it easy to find relevant scenarios. Each use case includes sample SQL queries to help you get started with implementation. From 32d8e83b6856dd47664976a556b79adb5e86be30 Mon Sep 17 00:00:00 2001 From: Alex Hullah Date: Sat, 5 Oct 2024 00:17:36 +0100 Subject: [PATCH 09/22] Adding Usability Constraints for Aggregation (#559) Adding Usability Constraints for Aggregation, to support commitment utilization calculation --------- Co-authored-by: Irena Jurica Co-authored-by: Christopher Harris Co-authored-by: Joaquin --- specification/columns/commitmentdiscountquantity.md | 6 ++++-- specification/columns/contractedcost.md | 6 ++++-- specification/columns/contractedunitprice.md | 4 ++++ specification/columns/listcost.md | 6 ++++-- specification/columns/listunitprice.md | 4 ++++ specification/columns/pricingquantity.md | 6 +++++- 6 files changed, 25 insertions(+), 7 deletions(-) diff --git a/specification/columns/commitmentdiscountquantity.md b/specification/columns/commitmentdiscountquantity.md index 892b103f5..b78b40965 100644 --- a/specification/columns/commitmentdiscountquantity.md +++ b/specification/columns/commitmentdiscountquantity.md @@ -4,8 +4,6 @@ Commitment Discount Quantity is the amount of a [*commitment discount*](#commitm When *CommitmentDiscountCategory* is "Usage" (usage-based *commitment discounts*), the Commitment Discount Quantity reflects the predefined amount of usage purchased or consumed. If [*commitment discount flexibility*](glossary:commitment-discount-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*. @@ -36,6 +34,10 @@ Commitment Discount Quantity The amount of a *commitment discount* purchased or accounted for in *commitment discount* related *rows* that is denominated in *Commitment Discount Units*. +## Usability Constraints + +**Aggregation:** When aggregating Commitment Discount Quantity for commitment 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*). Otherwise, when accounting for all upfront or accrued purchases, it's important to exclude *commitment discount* usage (i.e. when *ChargeCategory* is "Usage"). This exclusion helps prevent double counting of these quantities in the aggregation. + ## Content constraints | Constraint | Value | diff --git a/specification/columns/contractedcost.md b/specification/columns/contractedcost.md index e44233c8e..2c15aac25 100644 --- a/specification/columns/contractedcost.md +++ b/specification/columns/contractedcost.md @@ -2,8 +2,6 @@ Contracted Cost represents the cost calculated by multiplying [*contracted unit price*](#glossary:contracted-unit-price) and the corresponding [Pricing Quantity](#pricingquantity). Contracted Cost is denominated in the [Billing Currency](#billingcurrency) and is commonly used for calculating savings based on negotiation activities, by comparing it with [List Cost](#listcost). If [*negotiated discounts*](#glossary:negotiated-discount) are not applicable, the Contracted Cost defaults to the List Cost. -**Important:** When aggregating Contracted Cost for savings calculations, it's important to exclude either one-time or recurring charges ([Charge Category](#chargecategory) "Purchase") that are paid to cover future eligible charges (e.g., [Commitment Discount](#glossary:commitment-discount)) or the covered charges themselves. This exclusion helps prevent double counting of these charges in the aggregation. Which set of charges to exclude depends on whether cost are aggregated on a billed basis (exclude covered charges) or accrual basis (exclude Purchases for future charges). For instance, charges categorized as [Charge Category](#chargecategory) "Purchase" and their related [Charge Category](#chargecategory) "Tax" charges for a Commitment Discount might be excluded from an accrual basis cost aggregation of Contracted Cost. This is because the "Usage" and "Tax" charge records provided during the term of the commitment discount already specify the Contracted Cost. Purchase charges that cover future eligible charges can be identified by filtering for [Charge Category](#chargecategory) "Purchase" records with a [Billed Cost](#billedcost) greater than 0 and an [Effective Cost](#effectivecost) equal to 0. - The ContractedCost column MUST be present in a FOCUS dataset and MUST NOT be null. This column MUST be of type Decimal, MUST conform to [Numeric Format](#numericformat) requirements, and be denominated in the BillingCurrency. When [ContractedUnitPrice](#contractedunitprice) is present and not null, multiplying the ContractedUnitPrice by PricingQuantity MUST produce the ContractedCost, except in cases of [ChargeClass](#chargeclass) "Correction", which may address PricingQuantity or any cost discrepancies independently. In cases where the ContractedUnitPrice is present and null, the following applies: @@ -23,6 +21,10 @@ Contracted Cost Cost calculated by multiplying *contracted unit price* and the corresponding Pricing Quantity. +## Usability Constraints + +**Aggregation:** When aggregating Contracted Cost for savings calculations, it's important to exclude either [Charge Category](#chargecategory) "Purchase" charges (one-time and recurring) that are paid to cover future eligible charges (e.g., [Commitment Discount](#glossary:commitment-discount)) or the covered [Charge Category](#chargecategory) "Usage" charges themselves. This exclusion helps prevent double counting of these charges in the aggregation. Which set of charges to exclude depends on whether cost are aggregated on a billed basis (exclude covered charges) or accrual basis (exclude Purchases for future charges). For instance, charges categorized as [Charge Category](#chargecategory) "Purchase" and their related [Charge Category](#chargecategory) "Tax" charges for a Commitment Discount might be excluded from an accrual basis cost aggregation of Contracted Cost. This is because the "Usage" and "Tax" charge records provided during the term of the commitment discount already specify the Contracted Cost. Purchase charges that cover future eligible charges can be identified by filtering for [Charge Category](#chargecategory) "Purchase" records with a [Billed Cost](#billedcost) greater than 0 and an [Effective Cost](#effectivecost) equal to 0. + ## Content Constraints | Constraint | Value | diff --git a/specification/columns/contractedunitprice.md b/specification/columns/contractedunitprice.md index 4061d0ec3..d0deec909 100644 --- a/specification/columns/contractedunitprice.md +++ b/specification/columns/contractedunitprice.md @@ -16,6 +16,10 @@ Contracted Unit Price The agreed-upon unit price for a single Pricing Unit of the associated SKU, inclusive of negotiated discounts, if present, while excluding negotiated commitment discounts or any other discounts. +## Usability Constraints + +**Aggregation:** Column values should only be viewed in the context of their row and not aggregated to produce a total. + ## Content Constraints | Constraint | Value | diff --git a/specification/columns/listcost.md b/specification/columns/listcost.md index de5fabc87..cb0e69877 100644 --- a/specification/columns/listcost.md +++ b/specification/columns/listcost.md @@ -2,8 +2,6 @@ List Cost represents the cost calculated by multiplying the [*list unit price*](#glossary:list-unit-price) and the corresponding [Pricing Quantity](#pricingquantity). List Cost is denominated in the [Billing Currency](#billingcurrency) and is commonly used for calculating savings based on various rate optimization activities, by comparing it with [Contracted Cost](#contractedcost), [Billed Cost](#billedcost) and [Effective Cost](#effectivecost). -**Important:** When aggregating List Cost for savings calculations, it's important to exclude either one-time or recurring charges ([Charge Category](#chargecategory) "Purchase") that are paid to cover future eligible charges (e.g., [Commitment Discount](#glossary:commitment-discount)) or the covered charges themselves. This exclusion helps prevent double counting of these charges in the aggregation. Which set of charges to exclude depends on whether cost are aggregated on a billed basis (exclude covered charges) or accrual basis (exclude Purchases for future charges). For instance, charges categorized as [Charge Category](#chargecategory) "Purchase" and their related [Charge Category](#chargecategory) "Tax" charges for a Commitment Discount might be excluded from an accrual basis cost aggregation of List Cost. This is because the "Usage" and "Tax" charge records provided during the term of the commitment discount already specify the List Cost. Purchase charges that cover future eligible charges can be identified by filtering for [Charge Category](#chargecategory) "Purchase" records with a [Billed Cost](#billedcost) greater than 0 and an [Effective Cost](#effectivecost) equal to 0. - The ListCost column MUST be present in a FOCUS dataset and MUST NOT be null. This column MUST be of type Decimal, MUST conform to [Numeric Format](#numericformat) requirements, and be denominated in the BillingCurrency. When [ListUnitPrice](#listunitprice) is present and not null, multiplying the ListUnitPrice by PricingQuantity MUST produce the ListCost, except in cases of [ChargeClass](#chargeclass) "Correction", which may address PricingQuantity or any cost discrepancies independently. In cases where the ListUnitPrice is present and is null, the following applies: @@ -23,6 +21,10 @@ List Cost Cost calculated by multiplying List Unit Price and the corresponding Pricing Quantity. +## Usability Constraints + +**Aggregation:** When aggregating List Cost for savings calculations, it's important to exclude either [Charge Category](#chargecategory) "Purchase" charges (one-time and recurring) that are paid to cover future eligible charges (e.g., [Commitment Discount](#glossary:commitment-discount)) or the covered [Charge Category](#chargecategory) "Usage" charges themselves. This exclusion helps prevent double counting of these charges in the aggregation. Which set of charges to exclude depends on whether cost are aggregated on a billed basis (exclude covered charges) or accrual basis (exclude Purchases for future charges). For instance, charges categorized as [Charge Category](#chargecategory) "Purchase" and their related [Charge Category](#chargecategory) "Tax" charges for a Commitment Discount might be excluded from an accrual basis cost aggregation of List Cost. This is because the "Usage" and "Tax" charge records provided during the term of the commitment discount already specify the List Cost. Purchase charges that cover future eligible charges can be identified by filtering for [Charge Category](#chargecategory) "Purchase" records with a [Billed Cost](#billedcost) greater than 0 and an [Effective Cost](#effectivecost) equal to 0. + ## Content Constraints | Constraint | Value | diff --git a/specification/columns/listunitprice.md b/specification/columns/listunitprice.md index 531bd716c..c014b2382 100644 --- a/specification/columns/listunitprice.md +++ b/specification/columns/listunitprice.md @@ -16,6 +16,10 @@ List Unit Price The suggested provider-published unit price for a single Pricing Unit of the associated SKU, exclusive of any discounts. +## Usability Constraints + +**Aggregation:** Column values should only be viewed in the context of their row and not aggregated to produce a total. + ## Content Constraints | Constraint | Value | diff --git a/specification/columns/pricingquantity.md b/specification/columns/pricingquantity.md index b811cd71b..b858443da 100644 --- a/specification/columns/pricingquantity.md +++ b/specification/columns/pricingquantity.md @@ -16,7 +16,11 @@ Pricing Quantity The volume of a given SKU associated with a *resource* or *service* used or purchased, based on the Pricing Unit. -## Content constraints +## Usability Constraints + +**Aggregation:** When aggregating Pricing Quantity for commitment 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*). Otherwise, when accounting for all upfront or accrued purchases, it's important to exclude *commitment discount* usage (i.e. when *ChargeCategory* is "Usage"). This exclusion helps prevent double counting of these quantities in the aggregation. + +## Content Constraints | Constraint | Value | |:----------------|:--------------------------| From f4a26ecaf11252d39bff548c7e01cc73193bfc69 Mon Sep 17 00:00:00 2001 From: Joaquin Date: Tue, 8 Oct 2024 15:49:30 -0700 Subject: [PATCH 10/22] Editorial changes to columns names and ids (#588) _The changes in this PR are in accordance with the agreement that we will continue to use the previous version of the editorial guidelines in FOCUS version 1.1 (for details, see the table below)._
      Component Markdown (examples) Editorial Guidelines
      Column Names: Column Names:
      Pricing Quantity
      Pricing Unit
      Provider
      • Normal text without bold or italics.
      • Use the display name in the introductory (non-normative) section and description.
      • The first occurrence in a section is linked to the section, except when referring to itself.
      Attribute Names: Attribute Names:
      Currency Code Format
      Date/Time Format
      • Normal text without bold or italics.
      • Use the attribute display name in the introductory (non-normative) section, description, normative section, and content constraints table.
      • The first occurrence in a section is linked to the section, except when referring to itself.
      Column IDs: Column IDs:
      PricingQuantity
      PricingUnit
      ProviderName
      • Normal text without bold or italics.
      • Use the column ID in the normative section and when referencing column values.
      • For column IDs, use PascalCase (the first letter of every word is capitalized).
      • The first occurrence in a section is linked to the corresponding column, except when referring to itself.
      Glossary [*SKU*](#glossary:sku)
      [*resource*](#glossary:resource)
      [*service*](#glossary:service)
      • Italic.
      • The first occurrence in a section is linked to the glossary term.
      --------- Co-authored-by: Irena Jurica --- specification/columns/skupricedetails.md | 28 ++++++++++++------------ specification/columns/skupriceid.md | 16 +++++++------- 2 files changed, 22 insertions(+), 22 deletions(-) diff --git a/specification/columns/skupricedetails.md b/specification/columns/skupricedetails.md index fc4cb984e..a8f8381c3 100644 --- a/specification/columns/skupricedetails.md +++ b/specification/columns/skupricedetails.md @@ -1,22 +1,22 @@ # SKU Price Details -The **SKU Price Details** column represents a list of relevant properties shared by all charges with the same [**SKU Price ID**](#skupriceid). These properties provide qualitative and quantitative details about the service represented by a **SKU Price ID**. This can enable practitioners to calculate metrics such as total units of a service when it is not directly billed in those units (e.g. cores) and thus enables FinOps capabilities such as unit economics. These properties can also help a practitioner understand the specifics of a **SKU Price ID** and differentiate it other **SKU Price IDs**. +The SKU Price Details column represents a list of relevant properties shared by all charges with the same [SKU Price ID](#skupriceid). These properties provide qualitative and quantitative details about the service represented by a SKU Price ID. This can enable practitioners to calculate metrics such as total units of a service when it is not directly billed in those units (e.g. cores) and thus enables FinOps capabilities such as unit economics. These properties can also help a practitioner understand the specifics of a SKU Price ID and differentiate it other SKU Price IDs. -The *SkuPriceDetails* column adheres to the following requirements: +The SkuPriceDetails column adheres to the following requirements: -* The *SkuPriceDetails* column MUST be in [*KeyValueFormat*](#key-valueformat). +* The SkuPriceDetails column MUST be in [KeyValueFormat](#key-valueformat). * The key for a property SHOULD be formatted in [PascalCase](#glossary:pascalcase). -* The properties (both keys and values) contained in the *SkuPriceDetails* column MUST be shared across all charges having the same *SkuPriceId*, subject to the below provisions. - * Additional properties (key-value pairs) MAY be added to *SkuPriceDetails* going forward for a given *SkuPriceId*. - * Properties SHOULD NOT be removed from *SkuPriceDetails* for a given *SkuPriceId*, once they have been included. - * Individual properties (key-value pairs) SHOULD NOT be modified for a given *SkuPriceId* and SHOULD remain consistent over time. +* The properties (both keys and values) contained in the SkuPriceDetails column MUST be shared across all charges having the same SkuPriceId, subject to the below provisions. + * Additional properties (key-value pairs) MAY be added to SkuPriceDetails going forward for a given SkuPriceId. + * Properties SHOULD NOT be removed from SkuPriceDetails for a given SkuPriceId, once they have been included. + * Individual properties (key-value pairs) SHOULD NOT be modified for a given SkuPriceId and SHOULD remain consistent over time. * The key for a property SHOULD remain consistent across comparable SKUs having that property and the values for this key SHOULD remain in a consistent format. -* The *SkuPriceDetails* column MUST NOT contain properties which are not applicable to the corresponding *SkuPriceId*. -* The *SkuPriceDetails* column MAY contain properties which are already captured in other dedicated columns. -* If a property has a numeric value, it MUST represent the value for a single [*PricingUnit*](#pricingunit). -* The *SkuPriceDetails* column MUST be present in the billing data when the provider includes a *SkuPriceId*. - * The *SkuPriceDetails* column MAY be null when *SkuPriceId* is not null. - * The *SkuPriceDetails* column MUST be null when *SkuPriceId* is null. +* The SkuPriceDetails column MUST NOT contain properties which are not applicable to the corresponding SkuPriceId. +* The SkuPriceDetails column MAY contain properties which are already captured in other dedicated columns. +* If a property has a numeric value, it MUST represent the value for a single [PricingUnit](#pricingunit). +* The SkuPriceDetails column MUST be present in a [*FOCUS dataset*](#glossary:FOCUS-dataset) when the provider includes a SkuPriceId. + * The SkuPriceDetails column MAY be null when SkuPriceId is not null. + * The SkuPriceDetails column MUST be null when SkuPriceId is null. ## Examples @@ -39,7 +39,7 @@ SKU Price Details ## Description -A set of properties of a **SKU Price ID** which are meaningful and common to all instances of that **SKU Price ID**. +A set of properties of a SKU Price ID which are meaningful and common to all instances of that SKU Price ID. ## Content Constraints diff --git a/specification/columns/skupriceid.md b/specification/columns/skupriceid.md index dfbc94b54..69bf70a87 100644 --- a/specification/columns/skupriceid.md +++ b/specification/columns/skupriceid.md @@ -2,14 +2,14 @@ A SKU Price ID is a unique identifier that defines the unit price used to calculate the charge. SKU Price ID can be referenced on a [*price list*](#glossary:price-list) published by a provider to look up detailed information, including a corresponding list unit price. The composition of the properties associated with the SKU Price ID may differ across providers. SKU Price ID is commonly used for analyzing cost based on pricing properties such as Terms and Tiers. -The *SkuPriceId* column adheres to the following requirements: - -* *SkuPriceId* MUST be present in a FOCUS dataset when the provider publishes a SKU price list and MUST be of type String. -* *SkuPriceId* MUST define a single unit price used for calculating the charge. -* [*ListUnitPrice*](#listunitprice) MUST be associated with the *SkuPriceId* in the provider published price list. -* *SkuPriceId* MUST NOT be null when [*ChargeClass*](#chargeclass) is not "Correction" and [*ChargeCategory*](#chargecategory) is "Usage" or "Purchase", MUST be null when *ChargeCategory* is "Tax", and MAY be null for all other combinations of *ChargeClass* and *ChargeCategory*. -* A given value of *SkuPriceId* MUST be associated with one and only one [*SkuId*](#skuid), except in cases of [*commitment discount flexibility*](glossary:commitment-discount-flexibility). -* If a provider does not have a *SkuPriceId* and wants to include information in columns linked to *SkuPriceId* such as *ListUnitPrice* or [*SkuPriceDetails*](#skupricedetails), the *SkuId* MAY be used in the *SkuPriceId* column as long as it adheres to the above conditions. +The SkuPriceId column adheres to the following requirements: + +* SkuPriceId MUST be present in a [*FOCUS dataset*](#glossary:FOCUS-dataset) when the provider publishes a SKU price list and MUST be of type String. +* SkuPriceId MUST define a single unit price used for calculating the charge. +* [ListUnitPrice](#listunitprice) MUST be associated with the SkuPriceId in the provider published price list. +* SkuPriceId MUST NOT be null when [ChargeClass](#chargeclass) is not "Correction" and [ChargeCategory](#chargecategory) is "Usage" or "Purchase", MUST be null when ChargeCategory is "Tax", and MAY be null for all other combinations of ChargeClass and ChargeCategory. +* A given value of SkuPriceId MUST be associated with one and only one [SkuId](#skuid), except in cases of [commitment discount flexibility](#glossary:commitment-discount-flexibility). +* If a provider does not have a SkuPriceId and wants to include information in columns linked to SkuPriceId such as ListUnitPrice or [SkuPriceDetails](#skupricedetails), the SkuId MAY be used in the SkuPriceId column as long as it adheres to the above conditions. ## Column ID From 5f123bd8e9f643c26527f4228b05b862af89d656 Mon Sep 17 00:00:00 2001 From: Irena Jurica Date: Wed, 9 Oct 2024 00:49:55 +0200 Subject: [PATCH 11/22] Editorial changes to columns names and ids (part 2) (#589) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit _The changes in this PR are in accordance with the agreement that we will continue to use the previous version of the editorial guidelines in FOCUS version 1.1 (for details, see the table below)._
      Component Markdown (examples) Editorial Guidelines
      Column Names: Column Names:
      Pricing Quantity
      Pricing Unit
      Provider
      • Normal text without bold or italics.
      • Use the display name in the introductory (non-normative) section and description.
      • The first occurrence in a section is linked to the section, except when referring to itself.
      Attribute Names: Attribute Names:
      Currency Code Format
      Date/Time Format
      • Normal text without bold or italics.
      • Use the attribute display name in the introductory (non-normative) section, description, normative section, and content constraints table.
      • The first occurrence in a section is linked to the section, except when referring to itself.
      Column IDs: Column IDs:
      PricingQuantity
      PricingUnit
      ProviderName
      • Normal text without bold or italics.
      • Use the column ID in the normative section and when referencing column values.
      • For column IDs, use PascalCase (the first letter of every word is capitalized).
      • The first occurrence in a section is linked to the corresponding column, except when referring to itself.
      Glossary [*SKU*](#glossary:sku)
      [*resource*](#glossary:resource)
      [*service*](#glossary:service)
      • Italic.
      • The first occurrence in a section is linked to the glossary term.
      --- **Types of Editorial Changes:** - Aligned the **formatting** of references to columns (display name, ID) and glossary terms with the approach used in other columns. - Aligned **formatting of references to format attributes** in normative requirements, opting for the **attribute name instead of the attribute ID** (_see Note for reasoning_): - CommitmentDiscountUnit, ConsumedUnit and PricingUnit addressed in this PR - SkuPriceDetails addressed in PR #588 - Addressed several **missing and broken links** to columns and glossary terms. **Changes applied to the following columns:** - Commitment Discount Quantity - Commitment Discount Unit - Consumed Unit - Pricing Unit - Service Subcategory --- **Notes:** - I prefer using the attribute name over the attribute ID when referencing formatting attributes, at least for now, considering: - The attribute name was used in the Content Constraints tables in all instances. - The attribute name was used in the Normative Requirements in 13 instances. - The attribute ID was used in the Normative Requirements in only 4 instances (CommitmentDiscountUnit, ConsumedUnit, PricingUnit, SkuPriceDetails). - In 2 instances (ChargePeriodStart and ChargePeriodEnd), although listed in the constraints table, the requirement to follow the Date/Time format wasn’t explicitly mentioned in the normative requirements paragraph. I suggest addressing all Date/Time references in version 1.2 or later. --- .../columns/commitmentdiscountquantity.md | 24 +++++++++---------- .../columns/commitmentdiscountunit.md | 10 ++++---- specification/columns/pricingunit.md | 2 +- specification/columns/servicesubcategory.md | 2 +- 4 files changed, 19 insertions(+), 19 deletions(-) diff --git a/specification/columns/commitmentdiscountquantity.md b/specification/columns/commitmentdiscountquantity.md index b78b40965..464bc2dfe 100644 --- a/specification/columns/commitmentdiscountquantity.md +++ b/specification/columns/commitmentdiscountquantity.md @@ -1,24 +1,24 @@ # 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). +Commitment Discount Quantity is the amount of a [*commitment discount*](#glossary:commitment-discount) purchased or accounted for in *commitment discount* related [*rows*](#glossary:row) that is denominated in [Commitment Discount Units](#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* 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 discount flexibility*](glossary:commitment-discount-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. +When [CommitmentDiscountCategory](#commitmentdiscountcategory) is "Usage" (usage-based *commitment discounts*), the Commitment Discount Quantity reflects the predefined amount of usage purchased or consumed. If [*commitment discount flexibility*](#glossary:commitment-discount-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. 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 null or any valid decimal value if [*CommitmentDiscountId*](#commitmentdiscountid) is not null and [*ChargeClass*](#chargeclass) is "Correction". +* CommitmentDiscountQuantity MUST be of type Decimal and MUST conform to [NumericFormat](#numericformat) requirements. +* CommitmentDiscountQuantity MAY be null or any valid decimal value if [CommitmentDiscountId](#commitmentdiscountid) is not null and [ChargeClass](#chargeclass) is "Correction". -In cases where the *ChargeCategory* is "Purchase", *CommitmentDiscountId* is not null, and *ChargeClass* is not "Correction", the following applies: +In cases where the ChargeCategory is "Purchase", CommitmentDiscountId is not null, and ChargeClass is not "Correction", 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. +* 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", *CommitmentDiscountId* is not null, and *ChargeClass* is not "Correction", the following applies: +In cases where the ChargeCategory is "Usage", CommitmentDiscountId is not null, and ChargeClass is not "Correction", the following applies: -* When *CommitmentDiscountStatus* is "Used", CommitmentDiscountQuantity MUST be the positive, metered quantity of *CommitmentDiscountUnits* that is consumed over the *row's* *charge period*. -* When *CommitmentDiscountStatus* is "Unused", CommitmentDiscountQuantity MUST be the remaining, positive, unused quantity of *CommitmentDiscountUnits* for the *row's* *charge period*. +* When [CommitmentDiscountStatus](#commitmentdiscountstatus) is "Used", CommitmentDiscountQuantity MUST be the positive, metered quantity of CommitmentDiscountUnits that is consumed over the *row's* *charge period*. +* When CommitmentDiscountStatus is "Unused", CommitmentDiscountQuantity MUST be the remaining, positive, unused quantity of CommitmentDiscountUnits for the *row's* *charge period*. CommitmentDiscountQuantity MUST be null in all other cases. @@ -32,11 +32,11 @@ 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*. +The amount of a *commitment discount* purchased or accounted for in *commitment discount* related *rows* that is denominated in Commitment Discount Units. ## Usability Constraints -**Aggregation:** When aggregating Commitment Discount Quantity for commitment 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*). Otherwise, when accounting for all upfront or accrued purchases, it's important to exclude *commitment discount* usage (i.e. when *ChargeCategory* is "Usage"). This exclusion helps prevent double counting of these quantities in the aggregation. +**Aggregation:** When aggregating Commitment Discount Quantity for commitment 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*). Otherwise, when accounting for all upfront or accrued purchases, it's important to exclude *commitment discount* usage (i.e. when ChargeCategory is "Usage"). This exclusion helps prevent double counting of these quantities in the aggregation. ## Content constraints diff --git a/specification/columns/commitmentdiscountunit.md b/specification/columns/commitmentdiscountunit.md index fc91838b1..e64a03a5c 100644 --- a/specification/columns/commitmentdiscountunit.md +++ b/specification/columns/commitmentdiscountunit.md @@ -6,15 +6,15 @@ 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 MAY be null if [*CommitmentDiscountId*](#commitmentdiscountid) is not null and [*ChargeClass*](#chargeclass) is "Correction". -* CommitmentDiscountUnit MUST NOT be null when *CommitmentDiscountId* is not null and *ChargeClass* is not "Correction". +* The CommitmentDiscountUnit MUST be the same across all *rows* where CommitmentDiscountQuantity has the same [CommitmentDiscountId](#commitmentdiscountid). +* CommitmentDiscountUnit MAY be null if CommitmentDiscountId is not null and [ChargeClass](#chargeclass) is "Correction". +* CommitmentDiscountUnit MUST NOT be null when CommitmentDiscountId is not null and ChargeClass is not "Correction". * 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 discount flexibility*](glossary:commitment-discount-flexibility), the CommitmentDiscountUnit value SHOULD reflect this consideration. +* When accounting for [*commitment discount flexibility*](#glossary:commitment-discount-flexibility), the CommitmentDiscountUnit value SHOULD reflect this consideration. ## Column ID @@ -26,7 +26,7 @@ Commitment Discount Unit ## Description -The provider-specified measurement unit indicating how a provider measures the *Commitment Discount Quantity* of a *commitment discount*. +The provider-specified measurement unit indicating how a provider measures the Commitment Discount Quantity of a *commitment discount*. ## Content constraints diff --git a/specification/columns/pricingunit.md b/specification/columns/pricingunit.md index 3b4fca8db..dccea8655 100644 --- a/specification/columns/pricingunit.md +++ b/specification/columns/pricingunit.md @@ -2,7 +2,7 @@ The Pricing Unit represents a provider-specified measurement unit for determining unit prices, indicating how the provider rates measured usage and purchase quantities after applying pricing rules like [*block pricing*](#glossary:block-pricing). Common examples include the number of hours for compute appliance runtime (e.g. `Hours`), gigabyte-hours for a storage appliance (e.g., `GB-Hours`), or an accumulated count of requests for a network appliance or API service (e.g., `1000 Requests`). Pricing Unit complements the [Pricing Quantity](#pricingquantity) metric. Distinct from the [Consumed Unit](#consumedunit), it focuses on pricing and cost, not [*resource*](#glossary:resource) and [*service*](#glossary:service) consumption, often at a coarser granularity. -The PricingUnit column MUST be present in a FOCUS dataset. This column MUST be of type String. It MUST NOT be null when [ChargeClass](#chargeclass) is not "Correction" and [ChargeCategory](#chargecategory) is "Usage" or "Purchase", MUST be null when ChargeCategory is "Tax", and MAY be null for all other combinations of ChargeClass and ChargeCategory. Units of measure used in PricingUnit SHOULD adhere to the values and format requirements specified in the [UnitFormat](#unitformat) attribute. +The PricingUnit column MUST be present in a [*FOCUS dataset*](#glossary:FOCUS-dataset). This column MUST be of type String. It MUST NOT be null when [ChargeClass](#chargeclass) is not "Correction" and [ChargeCategory](#chargecategory) is "Usage" or "Purchase", MUST be null when ChargeCategory is "Tax", and MAY be null for all other combinations of ChargeClass and ChargeCategory. Units of measure used in PricingUnit SHOULD adhere to the values and format requirements specified in the [UnitFormat](#unitformat) attribute. The PricingUnit value MUST be semantically equal to the corresponding pricing measurement unit value provided in: diff --git a/specification/columns/servicesubcategory.md b/specification/columns/servicesubcategory.md index c353d039f..f235967fb 100644 --- a/specification/columns/servicesubcategory.md +++ b/specification/columns/servicesubcategory.md @@ -1,6 +1,6 @@ # Service Subcategory -The Service Subcategory is a secondary classification of the Service Category for a [*service*](#glossary:service) based on its core function. The Service Subcategory (in conjunction with the Service Category) is commonly used for scenarios like analyzing spend and usage for specific workload types across providers and tracking the migration of workloads across fundamentally different architectures. +The Service Subcategory is a secondary classification of the [Service Category](#servicecategory) for a [*service*](#glossary:service) based on its core function. The Service Subcategory (in conjunction with the Service Category) is commonly used for scenarios like analyzing spend and usage for specific workload types across providers and tracking the migration of workloads across fundamentally different architectures. The ServiceSubcategory column adheres to the following requirements: From 7971283e6591b288143dc39e13966a34ed07f332 Mon Sep 17 00:00:00 2001 From: Irena Jurica Date: Wed, 9 Oct 2024 00:50:30 +0200 Subject: [PATCH 12/22] Editorial changes to appendix - links to columns and glossary terms (#590) Editorial changes: - Commitment Discounts - Replaced column names previously formatted as code with links to columns - Addressed several missing and broken links to glossary terms - Grouping Constructs for Resources or Services - Added links to billing account, sub account, resource and service glossary terms - Origination of Cost Data - Added links to Provider, Publisher and Invoice Issuer columns - Added links to resource and service glossary terms --- _The changes in this PR are in accordance with the agreement that we will continue to use the previous version of the editorial guidelines in FOCUS version 1.1 (for details, see the table below)._
      Component Markdown (examples) Editorial Guidelines
      Column Names: Column Names:
      Pricing Quantity
      Pricing Unit
      Provider
      • Normal text without bold or italics.
      • Use the display name in the introductory (non-normative) section and description.
      • The first occurrence in a section is linked to the section, except when referring to itself.
      Attribute Names: Attribute Names:
      Currency Code Format
      Date/Time Format
      • Normal text without bold or italics.
      • Use the attribute display name in the introductory (non-normative) section, description, normative section, and content constraints table.
      • The first occurrence in a section is linked to the section, except when referring to itself.
      Column IDs: Column IDs:
      PricingQuantity
      PricingUnit
      ProviderName
      • Normal text without bold or italics.
      • Use the column ID in the normative section and when referencing column values.
      • For column IDs, use PascalCase (the first letter of every word is capitalized).
      • The first occurrence in a section is linked to the corresponding column, except when referring to itself.
      Glossary [*SKU*](#glossary:sku)
      [*resource*](#glossary:resource)
      [*service*](#glossary:service)
      • Italic.
      • The first occurrence in a section is linked to the glossary term.
      --- specification/appendix/commitment_discounts.md | 16 ++++++++-------- ...g_constructs_for_resources_and_or_services.md | 6 +++--- .../appendix/origination_of_cost_data.md | 8 ++++---- 3 files changed, 15 insertions(+), 15 deletions(-) diff --git a/specification/appendix/commitment_discounts.md b/specification/appendix/commitment_discounts.md index ed4733c68..243502a74 100644 --- a/specification/appendix/commitment_discounts.md +++ b/specification/appendix/commitment_discounts.md @@ -1,17 +1,17 @@ # Commitment Discounts -A [*commitment discount*](glossary:commitment-discount) is a billing discount model that offers reduced rates on preselected [*SKUs*](#glossary:sku) in exchange for an obligated usage or spend amount over a predefined [*term*](glossary:term). *Commitment discounts* typically consist of purchase and usage records within cost and usage datasets. +A [*commitment discount*](#glossary:commitment-discount) is a billing discount model that offers reduced rates on preselected [*SKUs*](#glossary:sku) in exchange for an obligated usage or spend amount over a predefined [*term*](#glossary:term). *Commitment discounts* typically consist of purchase and usage records within cost and usage datasets. -Usage-based *commitment discounts* obligate a customer to a predetermined amount of usage over a preselected *term*. In some cases, usage-based *commitment discounts* also feature [*commitment discount flexibility*](glossary:commitment-discount-flexibility) which may expand the types of *resources* that a *commitment discount* can cover. It is important to note when mixing *commitment discounts* with and without *commitment discount flexibility*, the `CommitmentDiscountUnit` should reflect this difference. +Usage-based *commitment discounts* obligate a customer to a predetermined amount of usage over a preselected *term*. In some cases, usage-based *commitment discounts* also feature [*commitment discount flexibility*](#glossary:commitment-discount-flexibility) which may expand the types of [*resources*](#glossary:resource) that a *commitment discount* can cover. It is important to note when mixing *commitment discounts* with and without *commitment discount flexibility*, the [CommitmentDiscountUnit](#commitmentdiscountunit) should reflect this difference. -Spend-based commitment discounts obligate a customer to a predetermined amount of spend over a preselected *term*. In the usage examples below, each [*row*](glossary:row) measures the monetary amount of the hourly commit consumed by the *commitment discount*, so the `CommitmentDiscountUnit` chosen is "USD", or the [*billing currency*](glossary:billing-currency). +Spend-based commitment discounts obligate a customer to a predetermined amount of spend over a preselected *term*. In the usage examples below, each [*row*](#glossary:row) measures the monetary amount of the hourly commit consumed by the *commitment discount*, so the CommitmentDiscountUnit chosen is "USD", or the [*billing currency*](#glossary:billing-currency). ## Purchasing While customers are bound to the *term* of a *commitment discounts*, providers offer some or all of the following payment options before and/or during the *term*: * *All Upfront* - The *commitment discounts* is paid in full before the *term* begins. -* *No Upfront* - The *commitment discounts* is paid on a repeated basis, typically over each [*billing period*](glossary:billing-period) of the *term*. +* *No Upfront* - The *commitment discounts* is paid on a repeated basis, typically over each [*billing period*](#glossary:billing-period) of the *term*. * *Partial Upfront* - Some of the *commitment discounts* is paid before the *term* begins, and the rest is paid repeatedly over the *term*. For example, if a customer buys a 1-year, spend-based *commitment discount* with a $1.00 hourly commit and pays with the partial option, the *commitment discount's* payment consists of a one-time purchase in the beginning of the *term* *and* monthly recurring purchases with the following totals: @@ -21,7 +21,7 @@ For example, if a customer buys a 1-year, spend-based *commitment discount* with ## Usage -Commitment discounts follow a "use-it-or-lose-it" model where the [*amortization*](glossary:amortization) of a *commitment discount's* purchase applies evenly to eligible *resources* over each [*charge period*](glossary:charge-period) of the *term*. +Commitment discounts follow a "use-it-or-lose-it" model where the [*amortization*](#glossary:amortization) of a *commitment discount's* purchase applies evenly to eligible *resources* over each [*charge period*](#glossary:charge-period) of the *term*. For example, if a customer buys a spend-based *commitment discount* with a $1.00 hourly commit in January (31 days), only $1.00 is eligible for consumption for each hourly *charge period*. If a customer has eligible *resources* running during this *charge period*, an amount of up to $1.00 will be allocated to these *resources*. Conversely, if a customer does have eligible *resources* running that fully take advantage of this $1.00 during this *charge period*, then some or all of this amount will go to waste. @@ -31,9 +31,9 @@ Within the FOCUS specification, the following examples demonstrate how a *commit ### Purchase *Rows* -All *commitment discount* purchases appear with a positive `BilledCost`, `PricingCategory` as "Standard", and with the *commitment discount's* id populating both the `ResourceId` and `CommitmentDiscountId` value. One-time purchases appear as a single record with `ChargeCategory` as "Purchase", `ChargeFrequency` as "One-Time", and the total quantity and units for *commitment discount's* *term* reflected as `CommitmentDiscountQuantity` and `CommitmentDiscountUnit`, respectively. +All *commitment discount* purchases appear with a positive [BilledCost](#billedcost), [PricingCategory](#pricingcategory) as "Standard", and with the *commitment discount's* id populating both the [ResourceId](#resourceid) and [CommitmentDiscountId](#commitmentdiscountid) value. One-time purchases appear as a single record with [ChargeCategory](#chargecategory) as "Purchase", [ChargeFrequency](#chargefrequency) as "One-Time", and the total quantity and units for *commitment discount's* *term* reflected as [CommitmentDiscountQuantity](#commitmentdiscountquantity) and CommitmentDiscountUnit, respectively. -Recurring purchases are allocated across all corresponding *charge periods* of the *term* when `ChargeCategory` is "Purchase", `ChargeFrequency` is "Recurring", and `CommitmentDiscountQuantity` and `CommitmentDiscountUnit` are reflected only for that *charge period*. +Recurring purchases are allocated across all corresponding *charge periods* of the *term* when ChargeCategory is "Purchase", ChargeFrequency is "Recurring", and CommitmentDiscountQuantity and CommitmentDiscountUnit are reflected only for that *charge period*. Using the same *commitment discount* example as above with a one-year, spend-based *commitment discount* with a $1.00 hourly commit purchased on Jan 1, 2023, various purchase options are available: @@ -166,7 +166,7 @@ In this scenario, one eligible *resource* runs for the full hour and consumes &d #### Scenario #2: No eligible *resource* consumes the allocated amount (0% utilization) -In this situation, the full eligible, $1.00 amount remained unutilized and results in 1 unused *row*. In this scenario, it is important to note that while `CommitmentDiscountQuantity` is not because $1 was still drawn down by the *commitment discount* even though, no *resource* was allocated, so `ConsumedQuantity` and `ConsumedUnit` are null. +In this situation, the full eligible, $1.00 amount remained unutilized and results in 1 unused *row*. In this scenario, it is important to note that while CommitmentDiscountQuantity is not because $1 was still drawn down by the *commitment discount* even though, no *resource* was allocated, so [ConsumedQuantity](#consumedquantity) and [ConsumedUnit](#consumedunit) are null. ```json [ diff --git a/specification/appendix/grouping_constructs_for_resources_and_or_services.md b/specification/appendix/grouping_constructs_for_resources_and_or_services.md index 76bb5b994..3fb69f94f 100644 --- a/specification/appendix/grouping_constructs_for_resources_and_or_services.md +++ b/specification/appendix/grouping_constructs_for_resources_and_or_services.md @@ -1,11 +1,11 @@ # Grouping constructs for resources or services -Providers natively support various constructs for grouping resources or services. These grouping constructs are often used to mimic organizational structures, technical architectures, cost attribution/allocation and access management boundaries, or other customer-specific structures based on requirements. +Providers natively support various constructs for grouping [*resources*](#glossary:resource) or [*services*](#glossary:service). These grouping constructs are often used to mimic organizational structures, technical architectures, cost attribution/allocation and access management boundaries, or other customer-specific structures based on requirements. Providers may support multiple levels of resource or service grouping mechanisms. FOCUS supports two distinct levels of groupings that are commonly needed for FinOps capabilities like chargeback, invoice reconciliation and cost allocation. -* Billing account: A mandatory container for resources or services that are billed together in an invoice. Billing accounts are commonly used for scenarios like grouping based on organizational constructs, invoice reconciliation and cost allocation strategies. -* Sub account: An optional provider-supported construct for organizing resources and services connected to a billing account. Sub accounts are commonly used for scenarios like grouping based on organizational constructs, access management needs and cost allocation strategies. Sub accounts must be associated with a billing account as they do not receive invoices. +* [*Billing account*](#glossary:billing-account): A mandatory container for *resources* or *services* that are billed together in an invoice. *Billing accounts* are commonly used for scenarios like grouping based on organizational constructs, invoice reconciliation and cost allocation strategies. +* [Sub account](#glossary:sub-account): An optional provider-supported construct for organizing *resources* and *services* connected to a *billing account*. *Sub accounts* are commonly used for scenarios like grouping based on organizational constructs, access management needs and cost allocation strategies. *Sub accounts* must be associated with a *billing account* as they do not receive invoices. The table below highlights key properties of the two grouping constructs supported by FOCUS. diff --git a/specification/appendix/origination_of_cost_data.md b/specification/appendix/origination_of_cost_data.md index 55ed959ba..4d5ffe239 100644 --- a/specification/appendix/origination_of_cost_data.md +++ b/specification/appendix/origination_of_cost_data.md @@ -2,11 +2,11 @@ Cost data presented in the billing datasets originates from various sources depending on the purchasing mechanism. There are at least 3 different pieces of information that are important for understanding where cost originated from. -* Provider: The entity that made the resources or services available for purchase. -* Publisher: The entity that produced the resources or services that were purchased. -* Invoice Issuer: The entity responsible for invoicing for the resources or services consumed. +* [Provider](#provider): The entity that made the [*resources*](#glossary:resource) or [*services*](#glossary:service) available for purchase. +* [Publisher](#publisher): The entity that produced the *resources* or *services* that were purchased. +* [Invoice Issuer](#invoiceissuer): The entity responsible for invoicing for the *resources* or *services* consumed. -The value for each of these may be different depending on the various purchasing scenarios for resources or services. Use cases for purchasing direct, via a Managed Service Provider (MSP), via a cloud marketplace, and from internal service offerings were considered. The table below presents a few scenarios to show how the value for each dimension may change based on the purchasing scenario. +The value for each of these may be different depending on the various purchasing scenarios for *resources* or *services*. Use cases for purchasing direct, via a Managed Service Provider (MSP), via a cloud marketplace, and from internal service offerings were considered. The table below presents a few scenarios to show how the value for each dimension may change based on the purchasing scenario. | # | Scenario | Provider | Publisher | Invoice Issuer | |:----|:----------------------------------------------------------------------------------------------------------------------------------------------|:-------------------------|:-----------------------------------------------------------------------------------------------------------------------|:-----------------------------------------------------------| From 16e9b1cf168bf7a4189e39d7f4f93146deb88995 Mon Sep 17 00:00:00 2001 From: Irena Jurica Date: Wed, 9 Oct 2024 00:51:04 +0200 Subject: [PATCH 13/22] Editorial changes to columns and glossary terms ordering (#591) Editorial changes (ordering): - Columns - Glossary terms --- specification/columns/columns.mdpp | 2 +- specification/glossary.md | 28 ++++++++++++++-------------- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/specification/columns/columns.mdpp b/specification/columns/columns.mdpp index c1dc78124..48cbb79f4 100644 --- a/specification/columns/columns.mdpp +++ b/specification/columns/columns.mdpp @@ -20,9 +20,9 @@ The FOCUS specification defines a group of columns that provide qualitative valu !INCLUDE "commitmentdiscountcategory.md",1 !INCLUDE "commitmentdiscountid.md",1 !INCLUDE "commitmentdiscountname.md",1 +!INCLUDE "commitmentdiscountquantity.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 diff --git a/specification/glossary.md b/specification/glossary.md index c09626a3f..443971a6a 100644 --- a/specification/glossary.md +++ b/specification/glossary.md @@ -44,6 +44,10 @@ A row in a FOCUS-compatible cost and usage dataset. The time window for which a charge is effective, inclusive of the start date and exclusive of the end date. The charge period for continuous usage should match the time granularity of the dataset (e.g., 1 hour for hourly, 1 day for daily). The charge period for a non-usage charge with time boundaries should match the duration of eligibility. +Cloud Service Provider (CSP) + +A company or organization that provides remote access to computing resources, infrastructure, or applications for a fee. + Commitment A customer's agreement to consume a specific quantity of a service or resource over a defined period, usually also creating a financial commitment throughout the entirety of the commitment period. Some commitments also hold Providers to certain assurance levels of resource availability. @@ -56,10 +60,6 @@ A billing discount model that offers reduced rates on preselected SKUs in exchan A feature of [*commitment discounts*](#glossary:commitment-discount) that may further transform the predetermined amount of usage purchased or consumed based on additional, provider-specific requirements. -Cloud Service Provider (CSP) - -A company or organization that provides remote access to computing resources, infrastructure, or applications for a fee. - Contracted Unit Price The agreed-upon unit price for a single [Pricing Unit](#pricingunit) of the associated SKU, inclusive of negotiated discounts, if present, and exclusive of any other discounts. This price is denominated in the [Billing Currency](#glossary:billingcurrency). @@ -100,14 +100,14 @@ A category of compute resources that can be paused or terminated by the CSP with The suggested provider-published unit price for a single [Pricing Unit](#pricingunit) of the associated [SKU](#glossary:sku), exclusive of any discounts. This price is denominated in the [Billing Currency](#glossary:billingcurrency). -Metric - -A FOCUS-defined column that provides numeric values, allowing for aggregation operations such as arithmetic operations (sum, multiplication, averaging etc.) and statistical operations. - Managed Service Provider (MSP) A company or organization that provides outsourced management and support of a range of IT services, such as network infrastructure, cybersecurity, cloud computing, and more. +Metric + +A FOCUS-defined column that provides numeric values, allowing for aggregation operations such as arithmetic operations (sum, multiplication, averaging etc.) and statistical operations. + Negotiated Discount A contractual agreement where a customer commits to specific spend or usage goals over a [*term*](#glossary:term) in exchange for discounted rates across varying SKUs. Unlike [*commitment discounts*](#glossary:commitment-discount), negotiated discounts are typically more customized to customer's accounts, can be utilized at varying frequencies, and may overlap with *commitment discounts*. @@ -120,22 +120,22 @@ A term that describes a service that is available and provided immediately or as Pascal Case (PascalCase, also known as UpperCamelCase) is a format for identifiers which contain one or more words meaning the words are concatenated together with no delimiter and the first letter of each word is capitalized. -Practitioner - -An individual who performs FinOps within an organization to maximize the business value of using cloud and cloud-like services. - Potato A long and often painful conversation had by the FOCUS contributors. Sometimes the name of a thing that we could not yet name. No starchy root vegetables were harmed during the production of this specification. We thank potato for its contribution in the creation of this specification. -Provider +Practitioner -An entity that made internal or 3rd party resources and/or services available for purchase. +An individual who performs FinOps within an organization to maximize the business value of using cloud and cloud-like services. Price List A comprehensive list of prices offered by a provider. +Provider + +An entity that made internal or 3rd party resources and/or services available for purchase. + Resource A unique component that incurs a charge. From 31276dd56269505d263e3a53d07c43737d27d428 Mon Sep 17 00:00:00 2001 From: Irena Jurica Date: Wed, 9 Oct 2024 01:08:19 +0200 Subject: [PATCH 14/22] Editorial changes: using attribute IDs when referencing attributes in normative paragraphs (#593) **Type of Editorial change:** Although attribute names were initially used for this purpose, for the sake of consistency and in accordance with the agreement made during the maintainers' meeting on Oct 8th, **switching from attribute names to attribute IDs in the normative paragraphs**, while retaining attribute names in the Content Constraints tables. **Scope of this PR:** This PR addresses references in the normative paragraphs of 12 columns and Metadata - CreationDate. For the remaining column, CommitmentDiscountQuantity, please refer to PR #589. --------- Co-authored-by: Joaquin --- specification/columns/billedcost.md | 2 +- specification/columns/billingcurrency.md | 2 +- specification/columns/billingperiodend.md | 2 +- specification/columns/billingperiodstart.md | 2 +- specification/columns/consumedquantity.md | 2 +- specification/columns/contractedcost.md | 2 +- specification/columns/contractedunitprice.md | 2 +- specification/columns/effectivecost.md | 2 +- specification/columns/listcost.md | 2 +- specification/columns/listunitprice.md | 2 +- specification/columns/pricingquantity.md | 2 +- specification/columns/tags.md | 2 +- specification/metadata/schema/creationdate.md | 2 +- 13 files changed, 13 insertions(+), 13 deletions(-) diff --git a/specification/columns/billedcost.md b/specification/columns/billedcost.md index da70e1d38..5daaa0285 100644 --- a/specification/columns/billedcost.md +++ b/specification/columns/billedcost.md @@ -2,7 +2,7 @@ The [*billed cost*](#glossary:billed-cost) represents a charge serving as the basis for invoicing, inclusive of the impacts of all reduced rates and discounts while excluding the [*amortization*](#glossary:amortization) of relevant purchases (one-time or recurring) paid to cover future eligible charges. This cost is denominated in the [Billing Currency](#billingcurrency). The Billed Cost is commonly used to perform FinOps capabilities that require cash-basis accounting such as cost allocation, budgeting, and invoice reconciliation. -The BilledCost column MUST be present in a FOCUS dataset and MUST NOT be null. This column MUST be of type Decimal, MUST conform to [Numeric Format](#numericformat), and be denominated in the BillingCurrency. The sum of the BilledCost for [*rows*](#glossary:row) in a given [*billing period*](#glossary:billing-period) MUST match the sum of the invoices received for that *billing period* for a [*billing account*](#glossary:billing-account). +The BilledCost column MUST be present in a FOCUS dataset and MUST NOT be null. This column MUST be of type Decimal, MUST conform to [NumericFormat](#numericformat), and be denominated in the BillingCurrency. The sum of the BilledCost for [*rows*](#glossary:row) in a given [*billing period*](#glossary:billing-period) MUST match the sum of the invoices received for that *billing period* for a [*billing account*](#glossary:billing-account). ## Column ID diff --git a/specification/columns/billingcurrency.md b/specification/columns/billingcurrency.md index 86ac91fa0..e60e127de 100644 --- a/specification/columns/billingcurrency.md +++ b/specification/columns/billingcurrency.md @@ -2,7 +2,7 @@ [*Billing currency*](#glossary:billing-currency) is an identifier that represents the currency that a charge for [*resources*](#glossary:resource) or [*services*](#glossary:service) was billed in. Billing Currency is commonly used in scenarios where costs need to be grouped or aggregated. -The BillingCurrency column MUST be present in a FOCUS dataset. BillingCurrency MUST match the currency used in the invoice generated by the invoice issuer. This column MUST be of type String and MUST NOT contain null values. BillingCurrency MUST conform to [Currency Code Format](#currencycodeformat) requirements. +The BillingCurrency column MUST be present in a FOCUS dataset. BillingCurrency MUST match the currency used in the invoice generated by the invoice issuer. This column MUST be of type String and MUST NOT contain null values. BillingCurrency MUST conform to [CurrencyCodeFormat](#currencycodeformat) requirements. ## Column ID diff --git a/specification/columns/billingperiodend.md b/specification/columns/billingperiodend.md index 9cd030e6d..fcd2cbaf2 100644 --- a/specification/columns/billingperiodend.md +++ b/specification/columns/billingperiodend.md @@ -2,7 +2,7 @@ Billing Period End represents the [*exclusive*](#glossary:exclusivebound) end date and time of a [*billing period*](#glossary:billing-period). For example, a time period where [BillingPeriodStart](#glossary:billingperiodstart) is '2024-01-01T00:00:00Z' and BillingPeriodEnd is '2024-02-01T00:00:00Z' includes charges for January, since BillingPeriodStart is [*inclusive*](#glossary:inclusivebound), but does not include charges for February since BillingPeriodEnd is *exclusive*. -The BillingPeriodEnd column MUST be present in a FOCUS dataset. This column MUST be of type [Date/Time Format](#date/timeformat), MUST be an *exclusive* value, and MUST NOT contain null values. The sum of the [BilledCost](#billedcost) column for [*rows*](#glossary:row) in a given *billing period* MUST match the sum of the invoices received for that *billing period* for a [*billing account*](#glossary:billing-account). +The BillingPeriodEnd column MUST be present in a FOCUS dataset. This column MUST be of type [DateTimeFormat](#date/timeformat), MUST be an *exclusive* value, and MUST NOT contain null values. The sum of the [BilledCost](#billedcost) column for [*rows*](#glossary:row) in a given *billing period* MUST match the sum of the invoices received for that *billing period* for a [*billing account*](#glossary:billing-account). ## Column ID diff --git a/specification/columns/billingperiodstart.md b/specification/columns/billingperiodstart.md index bc54163c5..54b198c31 100644 --- a/specification/columns/billingperiodstart.md +++ b/specification/columns/billingperiodstart.md @@ -2,7 +2,7 @@ Billing Period Start represents the [*inclusive*](#glossary:inclusivebound) start date and time of a [*billing period*](#glossary:billing-period). For example, a time period where BillingPeriodStart is '2024-01-01T00:00:00Z' and [BillingPeriodEnd](#billingperiodend) is '2024-02-01T00:00:00Z' includes charges for January, since BillingPeriodStart is inclusive, but does not include charges for February since BillingPeriodEnd is [*exclusive*](#glossary:exclusivebound). -The BillingPeriodStart column MUST be present in a FOCUS dataset, MUST be of type [Date/Time Format](#date/timeformat), MUST be an *inclusive* value, and MUST NOT contain null values. The sum of the [BilledCost](#billedcost) metric for [*rows*](#glossary:row) in a given *billing period* MUST match the sum of the invoices received for that *billing period* for a [*billing account*](#glossary:billing-account). +The BillingPeriodStart column MUST be present in a FOCUS dataset, MUST be of type [DateTimeFormat](#date/timeformat), MUST be an *inclusive* value, and MUST NOT contain null values. The sum of the [BilledCost](#billedcost) metric for [*rows*](#glossary:row) in a given *billing period* MUST match the sum of the invoices received for that *billing period* for a [*billing account*](#glossary:billing-account). ## Column ID diff --git a/specification/columns/consumedquantity.md b/specification/columns/consumedquantity.md index b29caa225..c4ffb19a3 100644 --- a/specification/columns/consumedquantity.md +++ b/specification/columns/consumedquantity.md @@ -5,7 +5,7 @@ The Consumed Quantity represents the volume of a metered SKU associated with a [ The ConsumedQuantity column adheres to the following requirements: * ConsumedQuantity MUST be present in a FOCUS dataset when the provider supports the measurement of usage. -* ConsumedQuantity MUST be of type Decimal and MUST conform to [Numeric Format](#numericformat) requirements. +* ConsumedQuantity MUST be of type Decimal and MUST conform to [NumericFormat](#numericformat) requirements. * ConsumedQuantity MUST NOT be null and MUST be a valid positive decimal value if [ChargeCategory](#chargecategory) is "Usage", [CommitmentDiscountStatus](#commitmentdiscountstatus) is not "Unused", and [ChargeClass](#chargeclass) is not "Correction". * ConsumedQuantity MAY be null or any valid decimal value if ChargeCategory is "Usage", CommitmentDiscountStatus is not "Unused", and ChargeClass is "Correction". * ConsumedQuantity MUST be null in all other cases. diff --git a/specification/columns/contractedcost.md b/specification/columns/contractedcost.md index 2c15aac25..8dda88594 100644 --- a/specification/columns/contractedcost.md +++ b/specification/columns/contractedcost.md @@ -2,7 +2,7 @@ Contracted Cost represents the cost calculated by multiplying [*contracted unit price*](#glossary:contracted-unit-price) and the corresponding [Pricing Quantity](#pricingquantity). Contracted Cost is denominated in the [Billing Currency](#billingcurrency) and is commonly used for calculating savings based on negotiation activities, by comparing it with [List Cost](#listcost). If [*negotiated discounts*](#glossary:negotiated-discount) are not applicable, the Contracted Cost defaults to the List Cost. -The ContractedCost column MUST be present in a FOCUS dataset and MUST NOT be null. This column MUST be of type Decimal, MUST conform to [Numeric Format](#numericformat) requirements, and be denominated in the BillingCurrency. When [ContractedUnitPrice](#contractedunitprice) is present and not null, multiplying the ContractedUnitPrice by PricingQuantity MUST produce the ContractedCost, except in cases of [ChargeClass](#chargeclass) "Correction", which may address PricingQuantity or any cost discrepancies independently. +The ContractedCost column MUST be present in a FOCUS dataset and MUST NOT be null. This column MUST be of type Decimal, MUST conform to [NumericFormat](#numericformat) requirements, and be denominated in the BillingCurrency. When [ContractedUnitPrice](#contractedunitprice) is present and not null, multiplying the ContractedUnitPrice by PricingQuantity MUST produce the ContractedCost, except in cases of [ChargeClass](#chargeclass) "Correction", which may address PricingQuantity or any cost discrepancies independently. In cases where the ContractedUnitPrice is present and null, the following applies: diff --git a/specification/columns/contractedunitprice.md b/specification/columns/contractedunitprice.md index d0deec909..796f84842 100644 --- a/specification/columns/contractedunitprice.md +++ b/specification/columns/contractedunitprice.md @@ -2,7 +2,7 @@ The Contracted Unit Price represents the agreed-upon unit price for a single [Pricing Unit](#pricingunit) of the associated SKU, inclusive of [*negotiated discounts*](#glossary:negotiated-discount), if present, while excluding negotiated [*commitment discounts*](#glossary:commitment-discount) or any other discounts. This price is denominated in the [Billing Currency](#billingcurrency). The Contracted Unit Price is commonly used for calculating savings based on negotiation activities. If negotiated discounts are not applicable, the Contracted Unit Price defaults to the [List Unit Price](#listunitprice). -The ContractedUnitPrice column MUST be present in a FOCUS dataset when the provider supports negotiated pricing concepts. This column MUST be a Decimal within the range of non-negative decimal values, MUST conform to [Numeric Format](#numericformat) requirements, and be denominated in the BillingCurrency. It MUST NOT be null when [ChargeClass](#chargeclass) is not "Correction" and [ChargeCategory](#chargecategory) is "Usage" or "Purchase", MUST be null when ChargeCategory is "Tax", and MAY be null for all other combinations of ChargeClass and ChargeCategory. When ContractedUnitPrice is present and not null, multiplying ContractedUnitPrice by [PricingQuantity](#pricingquantity) MUST equal [ContractedCost](#contractedcost), except in cases of ChargeClass "Correction", which may address PricingQuantity or any cost discrepancies independently. +The ContractedUnitPrice column MUST be present in a FOCUS dataset when the provider supports negotiated pricing concepts. This column MUST be a Decimal within the range of non-negative decimal values, MUST conform to [NumericFormat](#numericformat) requirements, and be denominated in the BillingCurrency. It MUST NOT be null when [ChargeClass](#chargeclass) is not "Correction" and [ChargeCategory](#chargecategory) is "Usage" or "Purchase", MUST be null when ChargeCategory is "Tax", and MAY be null for all other combinations of ChargeClass and ChargeCategory. When ContractedUnitPrice is present and not null, multiplying ContractedUnitPrice by [PricingQuantity](#pricingquantity) MUST equal [ContractedCost](#contractedcost), except in cases of ChargeClass "Correction", which may address PricingQuantity or any cost discrepancies independently. ## Column ID diff --git a/specification/columns/effectivecost.md b/specification/columns/effectivecost.md index 45424f4ff..d9758c1f6 100644 --- a/specification/columns/effectivecost.md +++ b/specification/columns/effectivecost.md @@ -7,7 +7,7 @@ This column resolves two challenges that are faced by practitioners: 1. Practitioners need to *amortize* relevant purchases, such as upfront fees, throughout the *commitment* and distribute them to the appropriate reporting groups (e.g. [*tags*](#glossary:tag), [*resources*](#glossary:resource)). 2. Many [*commitment discount*](#glossary:commitment-discount) constructs include a recurring expense for the *commitment* for every [*billing period*](#glossary:billing-period) and must distribute this cost to the *resources* using the *commitment*. This forces reconciliation between the initial *commitment* [*row*](#glossary:row) per period and the actual usage *rows*. -The EffectiveCost column MUST be present in a FOCUS dataset and MUST NOT be null. This column MUST be of type Decimal, MUST conform to [Numeric Format](#numericformat) requirements, and be denominated in the BillingCurrency. EffectiveCost MUST be 0 when ChargeCategory is "Purchase" and the purchase is intended to cover future eligible charges. The aggregated EffectiveCost for a billing period may not match the charge received on the invoice for the same *billing period*. +The EffectiveCost column MUST be present in a FOCUS dataset and MUST NOT be null. This column MUST be of type Decimal, MUST conform to [NumericFormat](#numericformat) requirements, and be denominated in the BillingCurrency. EffectiveCost MUST be 0 when ChargeCategory is "Purchase" and the purchase is intended to cover future eligible charges. The aggregated EffectiveCost for a billing period may not match the charge received on the invoice for the same *billing period*. In cases where the [ChargeCategory](#chargecategory) is not "Usage" or "Purchase", the following applies: diff --git a/specification/columns/listcost.md b/specification/columns/listcost.md index cb0e69877..ce644df93 100644 --- a/specification/columns/listcost.md +++ b/specification/columns/listcost.md @@ -2,7 +2,7 @@ List Cost represents the cost calculated by multiplying the [*list unit price*](#glossary:list-unit-price) and the corresponding [Pricing Quantity](#pricingquantity). List Cost is denominated in the [Billing Currency](#billingcurrency) and is commonly used for calculating savings based on various rate optimization activities, by comparing it with [Contracted Cost](#contractedcost), [Billed Cost](#billedcost) and [Effective Cost](#effectivecost). -The ListCost column MUST be present in a FOCUS dataset and MUST NOT be null. This column MUST be of type Decimal, MUST conform to [Numeric Format](#numericformat) requirements, and be denominated in the BillingCurrency. When [ListUnitPrice](#listunitprice) is present and not null, multiplying the ListUnitPrice by PricingQuantity MUST produce the ListCost, except in cases of [ChargeClass](#chargeclass) "Correction", which may address PricingQuantity or any cost discrepancies independently. +The ListCost column MUST be present in a FOCUS dataset and MUST NOT be null. This column MUST be of type Decimal, MUST conform to [NumericFormat](#numericformat) requirements, and be denominated in the BillingCurrency. When [ListUnitPrice](#listunitprice) is present and not null, multiplying the ListUnitPrice by PricingQuantity MUST produce the ListCost, except in cases of [ChargeClass](#chargeclass) "Correction", which may address PricingQuantity or any cost discrepancies independently. In cases where the ListUnitPrice is present and is null, the following applies: diff --git a/specification/columns/listunitprice.md b/specification/columns/listunitprice.md index c014b2382..86ffd1d78 100644 --- a/specification/columns/listunitprice.md +++ b/specification/columns/listunitprice.md @@ -2,7 +2,7 @@ The List Unit Price represents the suggested provider-published unit price for a single [Pricing Unit](#pricingunit) of the associated SKU, exclusive of any discounts. This price is denominated in the [Billing Currency](#billingcurrency). The List Unit Price is commonly used for calculating savings based on various rate optimization activities. -The ListUnitPrice column MUST be present in a FOCUS dataset when the provider publishes unit prices exclusive of discounts. This column MUST be a Decimal within the range of non-negative decimal values, MUST conform to [Numeric Format](#numericformat) requirements, and be denominated in the BillingCurrency. It MUST NOT be null when [ChargeClass](#chargeclass) is not "Correction" and [ChargeCategory](#chargecategory) is "Usage" or "Purchase", MUST be null when ChargeCategory is "Tax", and MAY be null for all other combinations of ChargeClass and ChargeCategory. When ListUnitPrice is present and is not null, multiplying ListUnitPrice by [PricingQuantity](#pricingquantity) MUST equal [ListCost](#listcost), except in cases of ChargeClass "Correction", which may address PricingQuantity or any cost discrepancies independently. +The ListUnitPrice column MUST be present in a FOCUS dataset when the provider publishes unit prices exclusive of discounts. This column MUST be a Decimal within the range of non-negative decimal values, MUST conform to [NumericFormat](#numericformat) requirements, and be denominated in the BillingCurrency. It MUST NOT be null when [ChargeClass](#chargeclass) is not "Correction" and [ChargeCategory](#chargecategory) is "Usage" or "Purchase", MUST be null when ChargeCategory is "Tax", and MAY be null for all other combinations of ChargeClass and ChargeCategory. When ListUnitPrice is present and is not null, multiplying ListUnitPrice by [PricingQuantity](#pricingquantity) MUST equal [ListCost](#listcost), except in cases of ChargeClass "Correction", which may address PricingQuantity or any cost discrepancies independently. ## Column ID diff --git a/specification/columns/pricingquantity.md b/specification/columns/pricingquantity.md index b858443da..940a1d5be 100644 --- a/specification/columns/pricingquantity.md +++ b/specification/columns/pricingquantity.md @@ -2,7 +2,7 @@ The Pricing Quantity represents the volume of a given SKU associated with a [*resource*](#glossary:resource) or [*service*](#glossary:service) used or purchased, based on the [Pricing Unit](#pricingunit). Distinct from [Consumed Quantity](#consumedquantity) (complementary to [Consumed Unit](#consumedunit)), it focuses on pricing and cost, not *resource* and *service* consumption. -The PricingQuantity column MUST be present in a FOCUS dataset. This column MUST be of type Decimal and MUST conform to [Numeric Format](#numericformat) requirements. The value MAY be negative in cases where [ChargeClass](#chargeclass) is "Correction". This column MUST NOT be null when [ChargeClass](#chargeclass) is not "Correction" and [ChargeCategory](#chargecategory) is "Usage" or "Purchase", MUST be null when ChargeCategory is "Tax", and MAY be null for all other combinations of ChargeClass and ChargeCategory. When unit prices are not null, multiplying PricingQuantity by a unit price MUST produce a result equal to the corresponding cost metric, except in cases of ChargeClass "Correction", which may address PricingQuantity or any cost discrepancies independently. +The PricingQuantity column MUST be present in a FOCUS dataset. This column MUST be of type Decimal and MUST conform to [NumericFormat](#numericformat) requirements. The value MAY be negative in cases where [ChargeClass](#chargeclass) is "Correction". This column MUST NOT be null when [ChargeClass](#chargeclass) is not "Correction" and [ChargeCategory](#chargecategory) is "Usage" or "Purchase", MUST be null when ChargeCategory is "Tax", and MAY be null for all other combinations of ChargeClass and ChargeCategory. When unit prices are not null, multiplying PricingQuantity by a unit price MUST produce a result equal to the corresponding cost metric, except in cases of ChargeClass "Correction", which may address PricingQuantity or any cost discrepancies independently. ## Column ID diff --git a/specification/columns/tags.md b/specification/columns/tags.md index f97b75d92..4a9c8039e 100644 --- a/specification/columns/tags.md +++ b/specification/columns/tags.md @@ -9,7 +9,7 @@ The Tags column adheres to the following requirements: * The Tags column MUST be present in a FOCUS dataset when the provider supports setting user or provider-defined tags. * The Tags column MUST contain user-defined and provider-defined tags. * The Tags column MUST only contain finalized tags. -* The Tags column MUST be in [Key-Value Format](#key-valueformat). +* The Tags column MUST be in [KeyValueFormat](#key-valueformat). * A Tag key with a non-null value for a given resource SHOULD be included in the tags column. * A Tag key with a null value for a given resource MAY be included in the tags column depending on the provider's tag finalization process. * A Tag key that does *not* support a corresponding value, MUST have a corresponding true (boolean) value set. diff --git a/specification/metadata/schema/creationdate.md b/specification/metadata/schema/creationdate.md index 77cbc92fd..2a1afc2bb 100644 --- a/specification/metadata/schema/creationdate.md +++ b/specification/metadata/schema/creationdate.md @@ -2,7 +2,7 @@ Date the schema was created. -The CreationDate MUST be present in the metadata. This MUST be of type Date/Time and MUST NOT contain null values. CreationDate MUST conform to [Date/Time Format](#date/timeformat). +The CreationDate MUST be present in the metadata. This MUST be of type Date/Time and MUST NOT contain null values. CreationDate MUST conform to [DateTimeFormat](#date/timeformat). ## Metadata ID From c6fb404623857192dbfb726d63d6debcbcad1a64 Mon Sep 17 00:00:00 2001 From: Irena Jurica Date: Wed, 9 Oct 2024 01:15:32 +0200 Subject: [PATCH 15/22] Editorial changes - links to FOCUS dataset glossary term (#592) Editorial changes: - Replaced ...MUST be present in the billing data... with ...MUST be present in a **[*FOCUS dataset*](#glossary:FOCUS-dataset)**... in the following columns: - CapacityReservation - ChargeClass - ConsumedUnit - SkuMeter - Added **links to the FOCUS dataset glossary term** for the remaining columns and other instances where the FOCUS dataset is mentioned. --- **Note:** For three columns, there are concurrent editorial PRs addressing column ID formatting and making changes to the same code line. To simplify the merge process and avoid conflicts, **links to the FOCUS dataset term** are not included in this PR but have been **added as suggestions in the respective PRs**: - SKU Price Details (see PR #588) - SKU Price ID (see PR #588) - Pricing Unit (see PR #589) --------- Co-authored-by: Joaquin --- EDITORIAL_GUIDELINES.md | 2 +- .../examples/metadata_examples/metadata_examples.mdpp | 2 +- .../metadata_examples/provider_version_changed_example.md | 2 +- specification/attributes/attributes.mdpp | 2 +- specification/attributes/column_naming_and_ordering.md | 2 +- specification/attributes/currency_code_format.md | 2 +- specification/attributes/datetime_format.md | 2 +- specification/attributes/key_value_format.md | 2 +- specification/attributes/numeric_format.md | 2 +- specification/attributes/string_handling.md | 2 +- specification/attributes/unit_format.md | 4 ++-- specification/columns/billedcost.md | 2 +- specification/columns/billingaccountid.md | 2 +- specification/columns/billingaccountname.md | 2 +- specification/columns/billingcurrency.md | 2 +- specification/columns/billingperiodend.md | 2 +- specification/columns/billingperiodstart.md | 2 +- specification/columns/capacityreservationid.md | 2 +- specification/columns/capacityreservationstatus.md | 2 +- specification/columns/chargecategory.md | 2 +- specification/columns/chargeclass.md | 2 +- specification/columns/chargedescription.md | 2 +- specification/columns/chargefrequency.md | 2 +- specification/columns/chargeperiodend.md | 2 +- specification/columns/chargeperiodstart.md | 2 +- specification/columns/commitmentdiscountcategory.md | 2 +- specification/columns/commitmentdiscountid.md | 2 +- specification/columns/commitmentdiscountname.md | 2 +- specification/columns/commitmentdiscountquantity.md | 6 +++--- specification/columns/commitmentdiscountstatus.md | 2 +- specification/columns/commitmentdiscounttype.md | 2 +- specification/columns/commitmentdiscountunit.md | 2 +- specification/columns/consumedquantity.md | 4 ++-- specification/columns/consumedunit.md | 2 +- specification/columns/contractedcost.md | 2 +- specification/columns/contractedunitprice.md | 2 +- specification/columns/effectivecost.md | 2 +- specification/columns/invoiceissuer.md | 2 +- specification/columns/listcost.md | 2 +- specification/columns/listunitprice.md | 2 +- specification/columns/pricingcategory.md | 2 +- specification/columns/pricingquantity.md | 2 +- specification/columns/provider.md | 2 +- specification/columns/publisher.md | 2 +- specification/columns/regionid.md | 2 +- specification/columns/regionname.md | 2 +- specification/columns/resourceid.md | 2 +- specification/columns/resourcename.md | 2 +- specification/columns/resourcetype.md | 2 +- specification/columns/servicecategory.md | 2 +- specification/columns/servicename.md | 2 +- specification/columns/servicesubcategory.md | 2 +- specification/columns/skuid.md | 2 +- specification/columns/skumeter.md | 4 ++-- specification/columns/subaccountid.md | 2 +- specification/columns/subaccountname.md | 2 +- specification/columns/tags.md | 2 +- specification/metadata/data_generator/datagenerator.md | 2 +- specification/metadata/metadata.mdpp | 2 +- .../schema/column_definition/column_definition.mdpp | 2 +- .../metadata/schema/column_definition/columnname.md | 2 +- specification/metadata/schema/column_definition/datatype.md | 2 +- .../schema/column_definition/providertagprefixes.md | 2 +- .../metadata/schema/column_definition/stringencoding.md | 2 +- specification/metadata/schema/focusversion.md | 2 +- specification/metadata/schema/providerversion.md | 2 +- specification/metadata/schema/schema.mdpp | 2 +- 67 files changed, 72 insertions(+), 72 deletions(-) diff --git a/EDITORIAL_GUIDELINES.md b/EDITORIAL_GUIDELINES.md index 189a612da..947acde16 100644 --- a/EDITORIAL_GUIDELINES.md +++ b/EDITORIAL_GUIDELINES.md @@ -136,7 +136,7 @@ These guidelines can be modified through a Pull Request (PR), which the members > > The **[Pricing Quantity](#pricing-quantity)** represents the volume of a given [SKU](#glossary:sku) associated with a [resource](#glossary:resource) or [service](#glossary:service) used or purchased, based on the **[Pricing Unit](#pricing-unit)**. Distinct from **[Consumed Quantity](#consumed-quantity)** (complementary to **[Consumed Unit](#consumed-unit)**), it focuses on pricing and cost, not resource and service consumption. > -> * The PricingQuantity column MUST be present in the billing data. +> * The PricingQuantity column MUST be present in a [*FOCUS dataset*](#glossary:FOCUS-dataset). > * This column MUST be of type Decimal and MUST conform to Numeric Format requirements. > * The value MAY be negative in cases where ChargeClass is "Correction". > diff --git a/specification/appendix/examples/metadata_examples/metadata_examples.mdpp b/specification/appendix/examples/metadata_examples/metadata_examples.mdpp index eae6ee5f2..971e1df8b 100644 --- a/specification/appendix/examples/metadata_examples/metadata_examples.mdpp +++ b/specification/appendix/examples/metadata_examples/metadata_examples.mdpp @@ -1,6 +1,6 @@ # Metadata Examples -The following sections contain examples of metadata provided by a hypothetical FOCUS data provider called ACME to supply the required reference between the FOCUS dataset and the schema metadata. Provider implementations will vary on how the metadata is disseminated; however, the provider's chosen metadata delivery approach should be able to support the structure represented in this example. +The following sections contain examples of metadata provided by a hypothetical FOCUS data provider called ACME to supply the required reference between the [*FOCUS dataset*](#glossary:FOCUS-dataset) and the schema metadata. Provider implementations will vary on how the metadata is disseminated; however, the provider's chosen metadata delivery approach should be able to support the structure represented in this example. In this example, the provider supports delivery of FOCUS data via file export to a data storage system. It uses JSON as the format for providing the metadata. The provider delivers data every 12 hours into a path structure described below: diff --git a/specification/appendix/examples/metadata_examples/provider_version_changed_example.md b/specification/appendix/examples/metadata_examples/provider_version_changed_example.md index ed912bacf..3284c5eed 100644 --- a/specification/appendix/examples/metadata_examples/provider_version_changed_example.md +++ b/specification/appendix/examples/metadata_examples/provider_version_changed_example.md @@ -2,7 +2,7 @@ ## Scenario -ACME specifies the optional metadata property [Provider Version](#providerversion) in their [Schema](#schema) object. They made a change to the FOCUS dataset they produce that does not adopt a new FOCUS Version, nor make a change the included columns but does impact values in the data. This example illustrates that Provider Version changes are independent of column changes, however provider version changes may include column changes. +ACME specifies the optional metadata property [Provider Version](#providerversion) in their [Schema](#schema) object. They made a change to the [*FOCUS dataset*](#glossary:FOCUS-dataset) they produce that does not adopt a new FOCUS Version, nor make a change the included columns but does impact values in the data. This example illustrates that Provider Version changes are independent of column changes, however provider version changes may include column changes. The provider creates a new schema object to represent the new schema. The provider includes both the FOCUS Version and Provider Version in the schema object. diff --git a/specification/attributes/attributes.mdpp b/specification/attributes/attributes.mdpp index 36fe447e9..595ceebba 100644 --- a/specification/attributes/attributes.mdpp +++ b/specification/attributes/attributes.mdpp @@ -1,6 +1,6 @@ # Attributes -Attributes are requirements that apply across a FOCUS dataset instead of an individual column level. Requirements on data content can include naming +Attributes are requirements that apply across a [*FOCUS dataset*](#glossary:FOCUS-dataset) instead of an individual column level. Requirements on data content can include naming conventions, data types, formatting standardizations, etc. Attributes may introduce high-level requirements for data granularity, recency, frequency, etc. Requirements defined in attributes are necessary for servicing [FinOps capabilities][FODOFC] accurately using a standard set of instructions regardless of the origin of the data. diff --git a/specification/attributes/column_naming_and_ordering.md b/specification/attributes/column_naming_and_ordering.md index d21360e03..410c61894 100644 --- a/specification/attributes/column_naming_and_ordering.md +++ b/specification/attributes/column_naming_and_ordering.md @@ -14,7 +14,7 @@ Column Naming and Ordering ## Description -Naming and ordering convention for columns appearing in a FOCUS dataset. +Naming and ordering convention for columns appearing in a [*FOCUS dataset*](#glossary:FOCUS-dataset). ## Requirements diff --git a/specification/attributes/currency_code_format.md b/specification/attributes/currency_code_format.md index 68c5b2a68..a0f53f449 100644 --- a/specification/attributes/currency_code_format.md +++ b/specification/attributes/currency_code_format.md @@ -14,7 +14,7 @@ Currency Code Format ## Description -Formatting for currency columns appearing in a FOCUS dataset. +Formatting for currency columns appearing in a [*FOCUS dataset*](#glossary:FOCUS-dataset). ## Requirements diff --git a/specification/attributes/datetime_format.md b/specification/attributes/datetime_format.md index d04b6e032..b6b013df7 100644 --- a/specification/attributes/datetime_format.md +++ b/specification/attributes/datetime_format.md @@ -14,7 +14,7 @@ Date/Time Format ## Description -Rules and formatting requirements for date/time-related columns appearing in a FOCUS dataset. +Rules and formatting requirements for date/time-related columns appearing in a [*FOCUS dataset*](#glossary:FOCUS-dataset). ## Requirements diff --git a/specification/attributes/key_value_format.md b/specification/attributes/key_value_format.md index 136d81447..9ae056915 100644 --- a/specification/attributes/key_value_format.md +++ b/specification/attributes/key_value_format.md @@ -14,7 +14,7 @@ Key-Value Format ## Description -Rules and formatting requirements for columns appearing in a FOCUS dataset that convey data as key-value pairs. +Rules and formatting requirements for columns appearing in a [*FOCUS dataset*](#glossary:FOCUS-dataset) that convey data as key-value pairs. ## Requirements diff --git a/specification/attributes/numeric_format.md b/specification/attributes/numeric_format.md index 992a60c56..cf9980562 100644 --- a/specification/attributes/numeric_format.md +++ b/specification/attributes/numeric_format.md @@ -14,7 +14,7 @@ Numeric Format ## Description -Rules and formatting requirements for numeric columns appearing in a FOCUS dataset. +Rules and formatting requirements for numeric columns appearing in a [*FOCUS dataset*](#glossary:FOCUS-dataset). ## Requirements diff --git a/specification/attributes/string_handling.md b/specification/attributes/string_handling.md index 108fb8f08..7beb1e014 100644 --- a/specification/attributes/string_handling.md +++ b/specification/attributes/string_handling.md @@ -14,7 +14,7 @@ String Handling ## Description -Requirements for string-capturing columns appearing in a FOCUS dataset. +Requirements for string-capturing columns appearing in a [*FOCUS dataset*](#glossary:FOCUS-dataset). ## Requirements diff --git a/specification/attributes/unit_format.md b/specification/attributes/unit_format.md index 7fa10a32c..929dc9cbb 100644 --- a/specification/attributes/unit_format.md +++ b/specification/attributes/unit_format.md @@ -1,6 +1,6 @@ # Unit Format -Billing data frequently captures data measured in units related to data size, count, time, and other [*dimensions*](#glossary:dimension). The Unit Format attribute provides a standard for expressing units of measure in columns appearing in a FOCUS dataset. +Billing data frequently captures data measured in units related to data size, count, time, and other [*dimensions*](#glossary:dimension). The Unit Format attribute provides a standard for expressing units of measure in columns appearing in a [*FOCUS dataset*](#glossary:FOCUS-dataset). All columns defined in FOCUS specifying Unit Format as a value format MUST follow the requirements listed below. @@ -14,7 +14,7 @@ Unit Format ## Description -Indicates standards for expressing measurement units in columns appearing in a FOCUS dataset. +Indicates standards for expressing measurement units in columns appearing in a *FOCUS dataset*. ## Requirements diff --git a/specification/columns/billedcost.md b/specification/columns/billedcost.md index 5daaa0285..eb54c5ec3 100644 --- a/specification/columns/billedcost.md +++ b/specification/columns/billedcost.md @@ -2,7 +2,7 @@ The [*billed cost*](#glossary:billed-cost) represents a charge serving as the basis for invoicing, inclusive of the impacts of all reduced rates and discounts while excluding the [*amortization*](#glossary:amortization) of relevant purchases (one-time or recurring) paid to cover future eligible charges. This cost is denominated in the [Billing Currency](#billingcurrency). The Billed Cost is commonly used to perform FinOps capabilities that require cash-basis accounting such as cost allocation, budgeting, and invoice reconciliation. -The BilledCost column MUST be present in a FOCUS dataset and MUST NOT be null. This column MUST be of type Decimal, MUST conform to [NumericFormat](#numericformat), and be denominated in the BillingCurrency. The sum of the BilledCost for [*rows*](#glossary:row) in a given [*billing period*](#glossary:billing-period) MUST match the sum of the invoices received for that *billing period* for a [*billing account*](#glossary:billing-account). +The BilledCost column MUST be present in a [*FOCUS dataset*](#glossary:FOCUS-dataset) and MUST NOT be null. This column MUST be of type Decimal, MUST conform to [Numeric Format](#numericformat), and be denominated in the BillingCurrency. The sum of the BilledCost for [*rows*](#glossary:row) in a given [*billing period*](#glossary:billing-period) MUST match the sum of the invoices received for that *billing period* for a [*billing account*](#glossary:billing-account). ## Column ID diff --git a/specification/columns/billingaccountid.md b/specification/columns/billingaccountid.md index e2b3a1a74..b66ccd0e0 100644 --- a/specification/columns/billingaccountid.md +++ b/specification/columns/billingaccountid.md @@ -2,7 +2,7 @@ A Billing Account ID is a provider-assigned identifier for a [*billing account*](#glossary:billing-account). *Billing accounts* are commonly used for scenarios like grouping based on organizational constructs, invoice reconciliation and cost allocation strategies. -The BillingAccountId column MUST be present in a FOCUS dataset. This column MUST be of type String and MUST NOT contain null values. BillingAccountId MUST be a globally unique identifier within a provider. +The BillingAccountId column MUST be present in a [*FOCUS dataset*](#glossary:FOCUS-dataset). This column MUST be of type String and MUST NOT contain null values. BillingAccountId MUST be a globally unique identifier within a provider. See [Appendix: Grouping constructs for resources or services](#groupingconstructsforresourcesorservices) for details and examples of the different grouping constructs supported by FOCUS. diff --git a/specification/columns/billingaccountname.md b/specification/columns/billingaccountname.md index b5ced23e6..cdfb8fe9b 100644 --- a/specification/columns/billingaccountname.md +++ b/specification/columns/billingaccountname.md @@ -2,7 +2,7 @@ A Billing Account Name is a display name assigned to a [*billing account*](#glossary:billing-account). *Billing accounts* are commonly used for scenarios like grouping based on organizational constructs, invoice reconciliation and cost allocation strategies. -The BillingAccountName column MUST be present in a FOCUS dataset and MUST NOT be null when the provider supports assigning a display name for the *billing account*. This column MUST be of type String. BillingAccountName MUST be unique within a customer when a customer has more than one *billing account*. +The BillingAccountName column MUST be present in a [*FOCUS dataset*](#glossary:FOCUS-dataset) and MUST NOT be null when the provider supports assigning a display name for the *billing account*. This column MUST be of type String. BillingAccountName MUST be unique within a customer when a customer has more than one *billing account*. See [Appendix: Grouping constructs for resources or services](#groupingconstructsforresourcesorservices) for details and examples of the different grouping constructs supported by FOCUS. diff --git a/specification/columns/billingcurrency.md b/specification/columns/billingcurrency.md index e60e127de..8dfd03818 100644 --- a/specification/columns/billingcurrency.md +++ b/specification/columns/billingcurrency.md @@ -2,7 +2,7 @@ [*Billing currency*](#glossary:billing-currency) is an identifier that represents the currency that a charge for [*resources*](#glossary:resource) or [*services*](#glossary:service) was billed in. Billing Currency is commonly used in scenarios where costs need to be grouped or aggregated. -The BillingCurrency column MUST be present in a FOCUS dataset. BillingCurrency MUST match the currency used in the invoice generated by the invoice issuer. This column MUST be of type String and MUST NOT contain null values. BillingCurrency MUST conform to [CurrencyCodeFormat](#currencycodeformat) requirements. +The BillingCurrency column MUST be present in a [*FOCUS dataset*](#glossary:FOCUS-dataset). BillingCurrency MUST match the currency used in the invoice generated by the invoice issuer. This column MUST be of type String and MUST NOT contain null values. BillingCurrency MUST conform to [Currency Code Format](#currencycodeformat) requirements. ## Column ID diff --git a/specification/columns/billingperiodend.md b/specification/columns/billingperiodend.md index fcd2cbaf2..f0303f384 100644 --- a/specification/columns/billingperiodend.md +++ b/specification/columns/billingperiodend.md @@ -2,7 +2,7 @@ Billing Period End represents the [*exclusive*](#glossary:exclusivebound) end date and time of a [*billing period*](#glossary:billing-period). For example, a time period where [BillingPeriodStart](#glossary:billingperiodstart) is '2024-01-01T00:00:00Z' and BillingPeriodEnd is '2024-02-01T00:00:00Z' includes charges for January, since BillingPeriodStart is [*inclusive*](#glossary:inclusivebound), but does not include charges for February since BillingPeriodEnd is *exclusive*. -The BillingPeriodEnd column MUST be present in a FOCUS dataset. This column MUST be of type [DateTimeFormat](#date/timeformat), MUST be an *exclusive* value, and MUST NOT contain null values. The sum of the [BilledCost](#billedcost) column for [*rows*](#glossary:row) in a given *billing period* MUST match the sum of the invoices received for that *billing period* for a [*billing account*](#glossary:billing-account). +The BillingPeriodEnd column MUST be present in a [*FOCUS dataset*](#glossary:FOCUS-dataset). This column MUST be of type [Date/Time Format](#date/timeformat), MUST be an *exclusive* value, and MUST NOT contain null values. The sum of the [BilledCost](#billedcost) column for [*rows*](#glossary:row) in a given *billing period* MUST match the sum of the invoices received for that *billing period* for a [*billing account*](#glossary:billing-account). ## Column ID diff --git a/specification/columns/billingperiodstart.md b/specification/columns/billingperiodstart.md index 54b198c31..9289a10ea 100644 --- a/specification/columns/billingperiodstart.md +++ b/specification/columns/billingperiodstart.md @@ -2,7 +2,7 @@ Billing Period Start represents the [*inclusive*](#glossary:inclusivebound) start date and time of a [*billing period*](#glossary:billing-period). For example, a time period where BillingPeriodStart is '2024-01-01T00:00:00Z' and [BillingPeriodEnd](#billingperiodend) is '2024-02-01T00:00:00Z' includes charges for January, since BillingPeriodStart is inclusive, but does not include charges for February since BillingPeriodEnd is [*exclusive*](#glossary:exclusivebound). -The BillingPeriodStart column MUST be present in a FOCUS dataset, MUST be of type [DateTimeFormat](#date/timeformat), MUST be an *inclusive* value, and MUST NOT contain null values. The sum of the [BilledCost](#billedcost) metric for [*rows*](#glossary:row) in a given *billing period* MUST match the sum of the invoices received for that *billing period* for a [*billing account*](#glossary:billing-account). +The BillingPeriodStart column MUST be present in a [*FOCUS dataset*](#glossary:FOCUS-dataset), MUST be of type [Date/Time Format](#date/timeformat), MUST be an *inclusive* value, and MUST NOT contain null values. The sum of the [BilledCost](#billedcost) metric for [*rows*](#glossary:row) in a given *billing period* MUST match the sum of the invoices received for that *billing period* for a [*billing account*](#glossary:billing-account). ## Column ID diff --git a/specification/columns/capacityreservationid.md b/specification/columns/capacityreservationid.md index ddc836936..bd87afd80 100644 --- a/specification/columns/capacityreservationid.md +++ b/specification/columns/capacityreservationid.md @@ -4,7 +4,7 @@ A Capacity Reservation ID is the identifier assigned to a [*capacity reservation The CapacityReservationId column adheres to the following requirements: -* CapacityReservationId MUST be present in the billing data when the provider supports *capacity reservations* and MUST be of type String. +* CapacityReservationId MUST be present in a [*FOCUS dataset*](#glossary:FOCUS-dataset) when the provider supports *capacity reservations* and MUST be of type String. * CapacityReservationId SHOULD NOT be null when a charge is related to a capacity reservation. * CapacityReservationId MUST NOT be null when a charge represents the unused portion of a *capacity reservation*. * CapacityReservationId MUST be null when a charge is not related to a *capacity reservation*. diff --git a/specification/columns/capacityreservationstatus.md b/specification/columns/capacityreservationstatus.md index 24b449c29..afc139b2e 100644 --- a/specification/columns/capacityreservationstatus.md +++ b/specification/columns/capacityreservationstatus.md @@ -4,7 +4,7 @@ Capacity Reservation Status indicates whether the charge represents either the c The CapacityReservationStatus column adheres to the following requirements: -* CapacityReservationStatus MUST be present in a FOCUS dataset when the provider supports *capacity reservations* and MUST be of type String. +* CapacityReservationStatus MUST be present in a [*FOCUS dataset*](#glossary:FOCUS-dataset) when the provider supports *capacity reservations* and MUST be of type String. * CapacityReservationStatus MUST be null when CapacityReservationId is null. * CapacityReservationStatus MUST NOT be null when CapacityReservationId is not null and [ChargeCategory](#chargecategory) is "Usage". * CapacityReservationStatus MUST be one of the allowed values. diff --git a/specification/columns/chargecategory.md b/specification/columns/chargecategory.md index 41f183c26..e3e672ad9 100644 --- a/specification/columns/chargecategory.md +++ b/specification/columns/chargecategory.md @@ -2,7 +2,7 @@ Charge Category represents the highest-level classification of a charge based on the nature of how it is billed. Charge Category is commonly used to identify and distinguish between types of charges that may require different handling. -The ChargeCategory column MUST be present in a FOCUS dataset and MUST NOT be null. This column is of type String and MUST be one of the allowed values. +The ChargeCategory column MUST be present in a [*FOCUS dataset*](#glossary:FOCUS-dataset) and MUST NOT be null. This column is of type String and MUST be one of the allowed values. ## Column ID diff --git a/specification/columns/chargeclass.md b/specification/columns/chargeclass.md index 41866810e..85569d6aa 100644 --- a/specification/columns/chargeclass.md +++ b/specification/columns/chargeclass.md @@ -2,7 +2,7 @@ Charge Class indicates whether the row represents a correction to a previously invoiced [*billing period*](#glossary:billing-period). Charge Class is commonly used to differentiate corrections from regularly incurred charges. -The ChargeClass column MUST be present in the FOCUS dataset. This column MUST be of type String and MUST be "Correction" when the row represents a correction to a previously invoiced *billing period*. ChargeClass MUST be null when it is not a correction or when it is a correction within the current *billing period*. +The ChargeClass column MUST be present in a [*FOCUS dataset*](#glossary:FOCUS-dataset). This column MUST be of type String and MUST be "Correction" when the row represents a correction to a previously invoiced *billing period*. ChargeClass MUST be null when it is not a correction or when it is a correction within the current *billing period*. ## Column ID diff --git a/specification/columns/chargedescription.md b/specification/columns/chargedescription.md index 0f875c6e4..e0b280f2e 100644 --- a/specification/columns/chargedescription.md +++ b/specification/columns/chargedescription.md @@ -2,7 +2,7 @@ A Charge Description provides a high-level context of a [*row*](#glossary:row) without requiring additional discovery. This column is a self-contained summary of the charge's purpose and price. It typically covers a select group of corresponding details across a billing dataset or provides information not otherwise available. -The ChargeDescription column MUST be present in a FOCUS dataset, MUST be of type String, and SHOULD NOT be null. Providers SHOULD specify the length of this column in their publicly available documentation. +The ChargeDescription column MUST be present in a [*FOCUS dataset*](#glossary:FOCUS-dataset), MUST be of type String, and SHOULD NOT be null. Providers SHOULD specify the length of this column in their publicly available documentation. ## Column ID diff --git a/specification/columns/chargefrequency.md b/specification/columns/chargefrequency.md index 45d94183c..3f5c1d825 100644 --- a/specification/columns/chargefrequency.md +++ b/specification/columns/chargefrequency.md @@ -2,7 +2,7 @@ Charge Frequency indicates how often a charge will occur. Along with the [charge period](#glossary:chargeperiod) related columns, the Charge Frequency is commonly used to understand recurrence periods (e.g., monthly, yearly), forecast upcoming charges, and differentiate between one-time and recurring fees for purchases. -The ChargeFrequency column is RECOMMENDED be present in a FOCUS dataset and MUST NOT be null. This column is of type String and MUST be one of the allowed values. When [ChargeCategory](#chargecategory) is "Purchase", ChargeFrequency MUST NOT be "Usage-Based". +The ChargeFrequency column is RECOMMENDED be present in a [*FOCUS dataset*](#glossary:FOCUS-dataset) and MUST NOT be null. This column is of type String and MUST be one of the allowed values. When [ChargeCategory](#chargecategory) is "Purchase", ChargeFrequency MUST NOT be "Usage-Based". ## Column ID diff --git a/specification/columns/chargeperiodend.md b/specification/columns/chargeperiodend.md index c7e5060e8..d0eccd134 100644 --- a/specification/columns/chargeperiodend.md +++ b/specification/columns/chargeperiodend.md @@ -2,7 +2,7 @@ Charge Period End represents the [*exclusive*](#glossary:exclusivebound) end date and time of a [*charge period*](#glossary:chargeperiod). For example, a time period where [ChargePeriodStart](#chargeperiodstart) is '2024-01-01T00:00:00Z' and ChargePeriodEnd is '2024-01-02T00:00:00Z' includes charges for January 1, since ChargePeriodStart is [*inclusive*](#glossary:inclusivebound), but does not include charges for January 2 since ChargePeriodEnd is *exclusive*. -ChargePeriodEnd MUST be present in a FOCUS dataset, MUST be of type Date/Time, MUST be an *exclusive* value, and MUST NOT contain null values. ChargePeriodEnd MUST match the ending date and time boundary of the effective period of the charge. +ChargePeriodEnd MUST be present in a [*FOCUS dataset*](#glossary:FOCUS-dataset), MUST be of type Date/Time, MUST be an *exclusive* value, and MUST NOT contain null values. ChargePeriodEnd MUST match the ending date and time boundary of the effective period of the charge. ## Column ID diff --git a/specification/columns/chargeperiodstart.md b/specification/columns/chargeperiodstart.md index fe701b161..2d4d4700a 100644 --- a/specification/columns/chargeperiodstart.md +++ b/specification/columns/chargeperiodstart.md @@ -2,7 +2,7 @@ Charge Period Start represents the [*inclusive*](#glossary:inclusivebound) start date and time within a [*charge period*](#glossary:chargeperiod). For example, a time period where ChargePeriodStart is '2024-01-01T00:00:00Z' and [ChargePeriodEnd](#chargeperiodend) is '2024-01-02T00:00:00Z' includes charges for January 1, since ChargePeriodStart is *inclusive*, but does not include charges for January 2 since ChargePeriodEnd is [*exclusive*](#glossary:exclusivebound). -ChargePeriodStart MUST be present in a FOCUS dataset, MUST be of type Date/Time, MUST be an *inclusive* value, and MUST NOT contain null values. ChargePeriodStart MUST match the beginning date and time boundary of the effective period of the charge. +ChargePeriodStart MUST be present in a [*FOCUS dataset*](#glossary:FOCUS-dataset), MUST be of type Date/Time, MUST be an *inclusive* value, and MUST NOT contain null values. ChargePeriodStart MUST match the beginning date and time boundary of the effective period of the charge. ## Column ID diff --git a/specification/columns/commitmentdiscountcategory.md b/specification/columns/commitmentdiscountcategory.md index 357642cfc..44c111b02 100644 --- a/specification/columns/commitmentdiscountcategory.md +++ b/specification/columns/commitmentdiscountcategory.md @@ -2,7 +2,7 @@ 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. +The CommitmentDiscountCategory column MUST be present in a [*FOCUS dataset*](#glossary: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. ## Column ID diff --git a/specification/columns/commitmentdiscountid.md b/specification/columns/commitmentdiscountid.md index 94eb9d435..958b13744 100644 --- a/specification/columns/commitmentdiscountid.md +++ b/specification/columns/commitmentdiscountid.md @@ -2,7 +2,7 @@ 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 ensure global uniqueness within the provider and SHOULD be a fully-qualified identifier. +The CommitmentDiscountId column MUST be present in a [*FOCUS dataset*](#glossary: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 diff --git a/specification/columns/commitmentdiscountname.md b/specification/columns/commitmentdiscountname.md index 66c8b1a84..72d2907ec 100644 --- a/specification/columns/commitmentdiscountname.md +++ b/specification/columns/commitmentdiscountname.md @@ -2,7 +2,7 @@ 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*. +The CommitmentDiscountName column MUST be present in a [*FOCUS dataset*](#glossary: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*. ## Column ID diff --git a/specification/columns/commitmentdiscountquantity.md b/specification/columns/commitmentdiscountquantity.md index 464bc2dfe..650e2f50d 100644 --- a/specification/columns/commitmentdiscountquantity.md +++ b/specification/columns/commitmentdiscountquantity.md @@ -6,9 +6,9 @@ When [CommitmentDiscountCategory](#commitmentdiscountcategory) is "Usage" (usage 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 [NumericFormat](#numericformat) requirements. -* CommitmentDiscountQuantity MAY be null or any valid decimal value if [CommitmentDiscountId](#commitmentdiscountid) is not null and [ChargeClass](#chargeclass) is "Correction". +* CommitmentDiscountQuantity MUST be present in a [*FOCUS dataset*](#glossary: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 null or any valid decimal value if [*CommitmentDiscountId*](#commitmentdiscountid) is not null and [*ChargeClass*](#chargeclass) is "Correction". In cases where the ChargeCategory is "Purchase", CommitmentDiscountId is not null, and ChargeClass is not "Correction", the following applies: diff --git a/specification/columns/commitmentdiscountstatus.md b/specification/columns/commitmentdiscountstatus.md index edc382186..2c5facecb 100644 --- a/specification/columns/commitmentdiscountstatus.md +++ b/specification/columns/commitmentdiscountstatus.md @@ -2,7 +2,7 @@ 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". CommitmentDiscountStatus MUST be one of the allowed values. +The CommitmentDiscountStatus column MUST be present in a [*FOCUS dataset*](#glossary: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". CommitmentDiscountStatus MUST be one of the allowed values. ## Column ID diff --git a/specification/columns/commitmentdiscounttype.md b/specification/columns/commitmentdiscounttype.md index 23cae2212..a88f1cf96 100644 --- a/specification/columns/commitmentdiscounttype.md +++ b/specification/columns/commitmentdiscounttype.md @@ -2,7 +2,7 @@ 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. +The CommitmentDiscountType column MUST be present in a [*FOCUS dataset*](#glossary: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. ## Column ID diff --git a/specification/columns/commitmentdiscountunit.md b/specification/columns/commitmentdiscountunit.md index e64a03a5c..596f4df77 100644 --- a/specification/columns/commitmentdiscountunit.md +++ b/specification/columns/commitmentdiscountunit.md @@ -4,7 +4,7 @@ Commitment Discount Unit represents the provider-specified measurement unit indi 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 present in a [*FOCUS dataset*](#glossary: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 MAY be null if CommitmentDiscountId is not null and [ChargeClass](#chargeclass) is "Correction". diff --git a/specification/columns/consumedquantity.md b/specification/columns/consumedquantity.md index c4ffb19a3..234f63b7e 100644 --- a/specification/columns/consumedquantity.md +++ b/specification/columns/consumedquantity.md @@ -4,8 +4,8 @@ The Consumed Quantity represents the volume of a metered SKU associated with a [ The ConsumedQuantity column adheres to the following requirements: -* ConsumedQuantity MUST be present in a FOCUS dataset when the provider supports the measurement of usage. -* ConsumedQuantity MUST be of type Decimal and MUST conform to [NumericFormat](#numericformat) requirements. +* ConsumedQuantity MUST be present in a [*FOCUS dataset*](#glossary:FOCUS-dataset) when the provider supports the measurement of usage. +* ConsumedQuantity MUST be of type Decimal and MUST conform to [Numeric Format](#numericformat) requirements. * ConsumedQuantity MUST NOT be null and MUST be a valid positive decimal value if [ChargeCategory](#chargecategory) is "Usage", [CommitmentDiscountStatus](#commitmentdiscountstatus) is not "Unused", and [ChargeClass](#chargeclass) is not "Correction". * ConsumedQuantity MAY be null or any valid decimal value if ChargeCategory is "Usage", CommitmentDiscountStatus is not "Unused", and ChargeClass is "Correction". * ConsumedQuantity MUST be null in all other cases. diff --git a/specification/columns/consumedunit.md b/specification/columns/consumedunit.md index 36d2760f6..a9f7b78bc 100644 --- a/specification/columns/consumedunit.md +++ b/specification/columns/consumedunit.md @@ -4,7 +4,7 @@ The Consumed Unit represents a provider-specified measurement unit indicating ho The ConsumedUnit column adheres to the following requirements: -* ConsumedUnit MUST be present in the billing data when the provider supports the measurement of usage. +* ConsumedUnit MUST be present in a [*FOCUS dataset*](#glossary:FOCUS-dataset) when the provider supports the measurement of usage. * ConsumedUnit MUST be of type String, and the units of measure used in ConsumedUnit SHOULD adhere to the values and format requirements specified in the [UnitFormat](#unitformat) attribute. * ConsumedUnit MUST NOT be null if [ChargeCategory](#chargecategory) is "Usage", [CommitmentDiscountStatus](#commitmentdiscountstatus) is not "Unused", and [ChargeClass](#chargeclass) is not "Correction". * ConsumedUnit MAY be null if ChargeCategory is "Usage", CommitmentDiscountStatus is not "Unused", and ChargeClass is "Correction". diff --git a/specification/columns/contractedcost.md b/specification/columns/contractedcost.md index 8dda88594..96a678312 100644 --- a/specification/columns/contractedcost.md +++ b/specification/columns/contractedcost.md @@ -2,7 +2,7 @@ Contracted Cost represents the cost calculated by multiplying [*contracted unit price*](#glossary:contracted-unit-price) and the corresponding [Pricing Quantity](#pricingquantity). Contracted Cost is denominated in the [Billing Currency](#billingcurrency) and is commonly used for calculating savings based on negotiation activities, by comparing it with [List Cost](#listcost). If [*negotiated discounts*](#glossary:negotiated-discount) are not applicable, the Contracted Cost defaults to the List Cost. -The ContractedCost column MUST be present in a FOCUS dataset and MUST NOT be null. This column MUST be of type Decimal, MUST conform to [NumericFormat](#numericformat) requirements, and be denominated in the BillingCurrency. When [ContractedUnitPrice](#contractedunitprice) is present and not null, multiplying the ContractedUnitPrice by PricingQuantity MUST produce the ContractedCost, except in cases of [ChargeClass](#chargeclass) "Correction", which may address PricingQuantity or any cost discrepancies independently. +The ContractedCost column MUST be present in a [*FOCUS dataset*](#glossary:FOCUS-dataset) and MUST NOT be null. This column MUST be of type Decimal, MUST conform to [Numeric Format](#numericformat) requirements, and be denominated in the BillingCurrency. When [ContractedUnitPrice](#contractedunitprice) is present and not null, multiplying the ContractedUnitPrice by PricingQuantity MUST produce the ContractedCost, except in cases of [ChargeClass](#chargeclass) "Correction", which may address PricingQuantity or any cost discrepancies independently. In cases where the ContractedUnitPrice is present and null, the following applies: diff --git a/specification/columns/contractedunitprice.md b/specification/columns/contractedunitprice.md index 796f84842..36d21392b 100644 --- a/specification/columns/contractedunitprice.md +++ b/specification/columns/contractedunitprice.md @@ -2,7 +2,7 @@ The Contracted Unit Price represents the agreed-upon unit price for a single [Pricing Unit](#pricingunit) of the associated SKU, inclusive of [*negotiated discounts*](#glossary:negotiated-discount), if present, while excluding negotiated [*commitment discounts*](#glossary:commitment-discount) or any other discounts. This price is denominated in the [Billing Currency](#billingcurrency). The Contracted Unit Price is commonly used for calculating savings based on negotiation activities. If negotiated discounts are not applicable, the Contracted Unit Price defaults to the [List Unit Price](#listunitprice). -The ContractedUnitPrice column MUST be present in a FOCUS dataset when the provider supports negotiated pricing concepts. This column MUST be a Decimal within the range of non-negative decimal values, MUST conform to [NumericFormat](#numericformat) requirements, and be denominated in the BillingCurrency. It MUST NOT be null when [ChargeClass](#chargeclass) is not "Correction" and [ChargeCategory](#chargecategory) is "Usage" or "Purchase", MUST be null when ChargeCategory is "Tax", and MAY be null for all other combinations of ChargeClass and ChargeCategory. When ContractedUnitPrice is present and not null, multiplying ContractedUnitPrice by [PricingQuantity](#pricingquantity) MUST equal [ContractedCost](#contractedcost), except in cases of ChargeClass "Correction", which may address PricingQuantity or any cost discrepancies independently. +The ContractedUnitPrice column MUST be present in a [*FOCUS dataset*](#glossary:FOCUS-dataset) when the provider supports negotiated pricing concepts. This column MUST be a Decimal within the range of non-negative decimal values, MUST conform to [Numeric Format](#numericformat) requirements, and be denominated in the BillingCurrency. It MUST NOT be null when [ChargeClass](#chargeclass) is not "Correction" and [ChargeCategory](#chargecategory) is "Usage" or "Purchase", MUST be null when ChargeCategory is "Tax", and MAY be null for all other combinations of ChargeClass and ChargeCategory. When ContractedUnitPrice is present and not null, multiplying ContractedUnitPrice by [PricingQuantity](#pricingquantity) MUST equal [ContractedCost](#contractedcost), except in cases of ChargeClass "Correction", which may address PricingQuantity or any cost discrepancies independently. ## Column ID diff --git a/specification/columns/effectivecost.md b/specification/columns/effectivecost.md index d9758c1f6..f54dec19d 100644 --- a/specification/columns/effectivecost.md +++ b/specification/columns/effectivecost.md @@ -7,7 +7,7 @@ This column resolves two challenges that are faced by practitioners: 1. Practitioners need to *amortize* relevant purchases, such as upfront fees, throughout the *commitment* and distribute them to the appropriate reporting groups (e.g. [*tags*](#glossary:tag), [*resources*](#glossary:resource)). 2. Many [*commitment discount*](#glossary:commitment-discount) constructs include a recurring expense for the *commitment* for every [*billing period*](#glossary:billing-period) and must distribute this cost to the *resources* using the *commitment*. This forces reconciliation between the initial *commitment* [*row*](#glossary:row) per period and the actual usage *rows*. -The EffectiveCost column MUST be present in a FOCUS dataset and MUST NOT be null. This column MUST be of type Decimal, MUST conform to [NumericFormat](#numericformat) requirements, and be denominated in the BillingCurrency. EffectiveCost MUST be 0 when ChargeCategory is "Purchase" and the purchase is intended to cover future eligible charges. The aggregated EffectiveCost for a billing period may not match the charge received on the invoice for the same *billing period*. +The EffectiveCost column MUST be present in a [*FOCUS dataset*](#glossary:FOCUS-dataset) and MUST NOT be null. This column MUST be of type Decimal, MUST conform to [Numeric Format](#numericformat) requirements, and be denominated in the BillingCurrency. EffectiveCost MUST be 0 when ChargeCategory is "Purchase" and the purchase is intended to cover future eligible charges. The aggregated EffectiveCost for a billing period may not match the charge received on the invoice for the same *billing period*. In cases where the [ChargeCategory](#chargecategory) is not "Usage" or "Purchase", the following applies: diff --git a/specification/columns/invoiceissuer.md b/specification/columns/invoiceissuer.md index 7a1b76edf..dfe03ed11 100644 --- a/specification/columns/invoiceissuer.md +++ b/specification/columns/invoiceissuer.md @@ -3,7 +3,7 @@ An Invoice Issuer is an entity responsible for invoicing for the [*resources*](#glossary:resource) or [*services*](#glossary:service) consumed. It is commonly used for cost analysis and reporting scenarios. -The InvoiceIssuer column MUST be present in a FOCUS dataset. This column MUST be of type String and MUST NOT contain null values. +The InvoiceIssuer column MUST be present in a [*FOCUS dataset*](#glossary:FOCUS-dataset). This column MUST be of type String and MUST NOT contain null values. See [Appendix: Origination of cost data](#originationofcostdata) section for examples of [Provider](#provider), [Publisher](#publisher) and Invoice Issuer values that can be used for various purchasing scenarios. diff --git a/specification/columns/listcost.md b/specification/columns/listcost.md index ce644df93..c2e6d3dd9 100644 --- a/specification/columns/listcost.md +++ b/specification/columns/listcost.md @@ -2,7 +2,7 @@ List Cost represents the cost calculated by multiplying the [*list unit price*](#glossary:list-unit-price) and the corresponding [Pricing Quantity](#pricingquantity). List Cost is denominated in the [Billing Currency](#billingcurrency) and is commonly used for calculating savings based on various rate optimization activities, by comparing it with [Contracted Cost](#contractedcost), [Billed Cost](#billedcost) and [Effective Cost](#effectivecost). -The ListCost column MUST be present in a FOCUS dataset and MUST NOT be null. This column MUST be of type Decimal, MUST conform to [NumericFormat](#numericformat) requirements, and be denominated in the BillingCurrency. When [ListUnitPrice](#listunitprice) is present and not null, multiplying the ListUnitPrice by PricingQuantity MUST produce the ListCost, except in cases of [ChargeClass](#chargeclass) "Correction", which may address PricingQuantity or any cost discrepancies independently. +The ListCost column MUST be present in a [*FOCUS dataset*](#glossary:FOCUS-dataset) and MUST NOT be null. This column MUST be of type Decimal, MUST conform to [Numeric Format](#numericformat) requirements, and be denominated in the BillingCurrency. When [ListUnitPrice](#listunitprice) is present and not null, multiplying the ListUnitPrice by PricingQuantity MUST produce the ListCost, except in cases of [ChargeClass](#chargeclass) "Correction", which may address PricingQuantity or any cost discrepancies independently. In cases where the ListUnitPrice is present and is null, the following applies: diff --git a/specification/columns/listunitprice.md b/specification/columns/listunitprice.md index 86ffd1d78..d35d73b32 100644 --- a/specification/columns/listunitprice.md +++ b/specification/columns/listunitprice.md @@ -2,7 +2,7 @@ The List Unit Price represents the suggested provider-published unit price for a single [Pricing Unit](#pricingunit) of the associated SKU, exclusive of any discounts. This price is denominated in the [Billing Currency](#billingcurrency). The List Unit Price is commonly used for calculating savings based on various rate optimization activities. -The ListUnitPrice column MUST be present in a FOCUS dataset when the provider publishes unit prices exclusive of discounts. This column MUST be a Decimal within the range of non-negative decimal values, MUST conform to [NumericFormat](#numericformat) requirements, and be denominated in the BillingCurrency. It MUST NOT be null when [ChargeClass](#chargeclass) is not "Correction" and [ChargeCategory](#chargecategory) is "Usage" or "Purchase", MUST be null when ChargeCategory is "Tax", and MAY be null for all other combinations of ChargeClass and ChargeCategory. When ListUnitPrice is present and is not null, multiplying ListUnitPrice by [PricingQuantity](#pricingquantity) MUST equal [ListCost](#listcost), except in cases of ChargeClass "Correction", which may address PricingQuantity or any cost discrepancies independently. +The ListUnitPrice column MUST be present in a [*FOCUS dataset*](#glossary:FOCUS-dataset) when the provider publishes unit prices exclusive of discounts. This column MUST be a Decimal within the range of non-negative decimal values, MUST conform to [Numeric Format](#numericformat) requirements, and be denominated in the BillingCurrency. It MUST NOT be null when [ChargeClass](#chargeclass) is not "Correction" and [ChargeCategory](#chargecategory) is "Usage" or "Purchase", MUST be null when ChargeCategory is "Tax", and MAY be null for all other combinations of ChargeClass and ChargeCategory. When ListUnitPrice is present and is not null, multiplying ListUnitPrice by [PricingQuantity](#pricingquantity) MUST equal [ListCost](#listcost), except in cases of ChargeClass "Correction", which may address PricingQuantity or any cost discrepancies independently. ## Column ID diff --git a/specification/columns/pricingcategory.md b/specification/columns/pricingcategory.md index ae0369498..504c807e9 100644 --- a/specification/columns/pricingcategory.md +++ b/specification/columns/pricingcategory.md @@ -4,7 +4,7 @@ Pricing Category describes the pricing model used for a charge at the time of us The PricingCategory column adheres to the following requirements: -* PricingCategory MUST be present in a FOCUS dataset when the provider supports more than one pricing category across all SKUs and MUST be of type String. +* PricingCategory MUST be present in a [*FOCUS dataset*](#glossary:FOCUS-dataset) when the provider supports more than one pricing category across all SKUs and MUST be of type String. * PricingCategory MUST NOT be null when [ChargeClass](#chargeclass) is not "Correction" and [ChargeCategory](#chargecategory) is "Usage" or "Purchase", MUST be null when ChargeCategory is "Tax", and MAY be null for all other combinations of ChargeClass and ChargeCategory. * PricingCategory MUST be one of the allowed values. * PricingCategory MUST be "Standard" when pricing is predetermined at the agreed upon rate for the [billing account](#glossary:billing-account). diff --git a/specification/columns/pricingquantity.md b/specification/columns/pricingquantity.md index 940a1d5be..2a10fb652 100644 --- a/specification/columns/pricingquantity.md +++ b/specification/columns/pricingquantity.md @@ -2,7 +2,7 @@ The Pricing Quantity represents the volume of a given SKU associated with a [*resource*](#glossary:resource) or [*service*](#glossary:service) used or purchased, based on the [Pricing Unit](#pricingunit). Distinct from [Consumed Quantity](#consumedquantity) (complementary to [Consumed Unit](#consumedunit)), it focuses on pricing and cost, not *resource* and *service* consumption. -The PricingQuantity column MUST be present in a FOCUS dataset. This column MUST be of type Decimal and MUST conform to [NumericFormat](#numericformat) requirements. The value MAY be negative in cases where [ChargeClass](#chargeclass) is "Correction". This column MUST NOT be null when [ChargeClass](#chargeclass) is not "Correction" and [ChargeCategory](#chargecategory) is "Usage" or "Purchase", MUST be null when ChargeCategory is "Tax", and MAY be null for all other combinations of ChargeClass and ChargeCategory. When unit prices are not null, multiplying PricingQuantity by a unit price MUST produce a result equal to the corresponding cost metric, except in cases of ChargeClass "Correction", which may address PricingQuantity or any cost discrepancies independently. +The PricingQuantity column MUST be present in a [*FOCUS dataset*](#glossary:FOCUS-dataset). This column MUST be of type Decimal and MUST conform to [Numeric Format](#numericformat) requirements. The value MAY be negative in cases where [ChargeClass](#chargeclass) is "Correction". This column MUST NOT be null when [ChargeClass](#chargeclass) is not "Correction" and [ChargeCategory](#chargecategory) is "Usage" or "Purchase", MUST be null when ChargeCategory is "Tax", and MAY be null for all other combinations of ChargeClass and ChargeCategory. When unit prices are not null, multiplying PricingQuantity by a unit price MUST produce a result equal to the corresponding cost metric, except in cases of ChargeClass "Correction", which may address PricingQuantity or any cost discrepancies independently. ## Column ID diff --git a/specification/columns/provider.md b/specification/columns/provider.md index e17f43e90..a88b07b69 100644 --- a/specification/columns/provider.md +++ b/specification/columns/provider.md @@ -2,7 +2,7 @@ A Provider is an entity that makes the [*resources*](#glossary:resource) or [*services*](#glossary:service) available for purchase. It is commonly used for cost analysis and reporting scenarios. -The Provider column MUST be present in a FOCUS dataset. This column MUST be of type String and MUST NOT contain null values. +The Provider column MUST be present in a [*FOCUS dataset*](#glossary:FOCUS-dataset). This column MUST be of type String and MUST NOT contain null values. See [Appendix: Origination of cost data](#originationofcostdata) section for examples of Provider, Publisher and Invoice Issuer values that can be used for various purchasing scenarios. diff --git a/specification/columns/publisher.md b/specification/columns/publisher.md index a9f5fd16c..14a407167 100644 --- a/specification/columns/publisher.md +++ b/specification/columns/publisher.md @@ -2,7 +2,7 @@ A Publisher is an entity that produces the [*resources*](#glossary:resource) or [*services*](#glossary:service) that were purchased. It is commonly used for cost analysis and reporting scenarios. -The Publisher column MUST be present in a FOCUS dataset. This column MUST be of type String and MUST NOT contain null values. +The Publisher column MUST be present in a [*FOCUS dataset*](#glossary:FOCUS-dataset). This column MUST be of type String and MUST NOT contain null values. See [Appendix: Origination of cost data](#originationofcostdata) section for examples of [Provider](#provider), Publisher and [Invoice Issuer](#invoiceissuer) values that can be used for various purchasing scenarios. diff --git a/specification/columns/regionid.md b/specification/columns/regionid.md index 873d036df..b1cada0e4 100644 --- a/specification/columns/regionid.md +++ b/specification/columns/regionid.md @@ -2,7 +2,7 @@ A Region ID is a provider-assigned identifier for an isolated geographic area where a [*resource*](#glossary:resource) is provisioned or a [*service*](#glossary:service) is provided. The region is commonly used for scenarios like analyzing cost and unit prices based on where *resources* are deployed. -The RegionId column MUST be present in a FOCUS dataset when the provider supports deploying resources or services within a *region* and MUST be of type String. RegionId MUST NOT be null when a *resource* or *service* is operated in or managed from a distinct region by the Provider and MAY contain null values when a *resource* or *service* is not restricted to an isolated geographic area. +The RegionId column MUST be present in a [*FOCUS dataset*](#glossary:FOCUS-dataset) when the provider supports deploying resources or services within a *region* and MUST be of type String. RegionId MUST NOT be null when a *resource* or *service* is operated in or managed from a distinct region by the Provider and MAY contain null values when a *resource* or *service* is not restricted to an isolated geographic area. ## Column ID diff --git a/specification/columns/regionname.md b/specification/columns/regionname.md index 934ca0b91..ee3092e51 100644 --- a/specification/columns/regionname.md +++ b/specification/columns/regionname.md @@ -2,7 +2,7 @@ Region Name is a provider-assigned display name for an isolated geographic area where a [*resource*](#glossary:resource) is provisioned or a [*service*](#glossary:service) is provided. Region Name is commonly used for scenarios like analyzing cost and unit prices based on where *resources* are deployed. -The RegionName column MUST be present in a FOCUS dataset when the provider supports deploying resources or services within a *region* and MUST be of type String. RegionName MUST NOT be null when a *resource* or *service* is operated in or managed from a distinct region by the Provider and MAY contain null values when a *resource* or *service* is not restricted to an isolated geographic area. +The RegionName column MUST be present in a [*FOCUS dataset*](#glossary:FOCUS-dataset) when the provider supports deploying resources or services within a *region* and MUST be of type String. RegionName MUST NOT be null when a *resource* or *service* is operated in or managed from a distinct region by the Provider and MAY contain null values when a *resource* or *service* is not restricted to an isolated geographic area. ## Column ID diff --git a/specification/columns/resourceid.md b/specification/columns/resourceid.md index e48d24d08..f494aa480 100644 --- a/specification/columns/resourceid.md +++ b/specification/columns/resourceid.md @@ -2,7 +2,7 @@ A Resource ID is an identifier assigned to a [*resource*](#glossary:resource) by the provider. The Resource ID is commonly used for cost reporting, analysis, and allocation scenarios. -The ResourceId column MUST be present in a FOCUS dataset when the provider supports billing based on provisioned resources. This column MUST be of type String. The ResourceId value MAY be a nullable column as some cost data [*rows*](#glossary:row) may not be associated with a *resource*. ResourceId MUST appear in the cost data if an identifier is assigned to a *resource* by the provider. ResourceId SHOULD be a fully-qualified identifier that ensures global uniqueness within the provider. +The ResourceId column MUST be present in a [*FOCUS dataset*](#glossary:FOCUS-dataset) when the provider supports billing based on provisioned resources. This column MUST be of type String. The ResourceId value MAY be a nullable column as some cost data [*rows*](#glossary:row) may not be associated with a *resource*. ResourceId MUST appear in the cost data if an identifier is assigned to a *resource* by the provider. ResourceId SHOULD be a fully-qualified identifier that ensures global uniqueness within the provider. ## Column ID diff --git a/specification/columns/resourcename.md b/specification/columns/resourcename.md index 524311b0c..71fa7a938 100644 --- a/specification/columns/resourcename.md +++ b/specification/columns/resourcename.md @@ -2,7 +2,7 @@ The Resource Name is a display name assigned to a [*resource*](#glossary:resource). It is commonly used for cost analysis, reporting, and allocation scenarios. -The ResourceName column MUST be present in a FOCUS dataset when the provider supports billing based on provisioned resources. This column MUST be of type String. The ResourceName value MAY be a nullable column as some cost data [*rows*](#glossary:row) may not be associated with a *resource* or because a display name cannot be assigned to a *resource*. ResourceName MUST NOT be null if a display name can be assigned to a *resource*. *Resources* not provisioned interactively or only have a system-generated [ResourceId](#resourceid) MUST NOT duplicate the same value as the ResourceName. +The ResourceName column MUST be present in a [*FOCUS dataset*](#glossary:FOCUS-dataset) when the provider supports billing based on provisioned resources. This column MUST be of type String. The ResourceName value MAY be a nullable column as some cost data [*rows*](#glossary:row) may not be associated with a *resource* or because a display name cannot be assigned to a *resource*. ResourceName MUST NOT be null if a display name can be assigned to a *resource*. *Resources* not provisioned interactively or only have a system-generated [ResourceId](#resourceid) MUST NOT duplicate the same value as the ResourceName. ## Column ID diff --git a/specification/columns/resourcetype.md b/specification/columns/resourcetype.md index 96480f78a..d05622c87 100644 --- a/specification/columns/resourcetype.md +++ b/specification/columns/resourcetype.md @@ -2,7 +2,7 @@ Resource Type describes the kind of [*resource*](#glossary:resource) the charge applies to. A Resource Type is commonly used for scenarios like identifying cost changes in groups of similar *resources* and may include values like Virtual Machine, Data Warehouse, and Load Balancer. -The ResourceType column MUST be present in a FOCUS dataset when the provider supports billing based on provisioned resources and supports assigning a type for resources. This column MUST be of type String and MUST NOT be null when a corresponding [ResourceId](#resourceid) is not null. When a corresponding ResourceId value is null, the ResourceType column value MUST also be null. +The ResourceType column MUST be present in a [*FOCUS dataset*](#glossary:FOCUS-dataset) when the provider supports billing based on provisioned resources and supports assigning a type for resources. This column MUST be of type String and MUST NOT be null when a corresponding [ResourceId](#resourceid) is not null. When a corresponding ResourceId value is null, the ResourceType column value MUST also be null. ## Column ID diff --git a/specification/columns/servicecategory.md b/specification/columns/servicecategory.md index c8d474fbb..77a83c41e 100644 --- a/specification/columns/servicecategory.md +++ b/specification/columns/servicecategory.md @@ -2,7 +2,7 @@ The Service Category is the highest-level classification of a [*service*](#glossary:service) based on the core function of the *service*. Each *service* should have one and only one category that best aligns with its primary purpose. The Service Category is commonly used for scenarios like analyzing costs across providers and tracking the migration of workloads across fundamentally different architectures. -The ServiceCategory column MUST be present in a FOCUS dataset and MUST NOT be null. This column is of type String and MUST be one of the allowed values. +The ServiceCategory column MUST be present in a [*FOCUS dataset*](#glossary:FOCUS-dataset) and MUST NOT be null. This column is of type String and MUST be one of the allowed values. ## Column ID diff --git a/specification/columns/servicename.md b/specification/columns/servicename.md index db1fc0cda..a5086cba1 100644 --- a/specification/columns/servicename.md +++ b/specification/columns/servicename.md @@ -4,7 +4,7 @@ A [*service*](#glossary:service) represents an offering that can be purchased fr The Service Name is a display name for the offering that was purchased. The Service Name is commonly used for scenarios like analyzing aggregate cost trends over time and filtering data to investigate anomalies. -The ServiceName column MUST be present in a FOCUS dataset. This column MUST be of type String and MUST NOT contain null values. +The ServiceName column MUST be present in a [*FOCUS dataset*](#glossary:FOCUS-dataset). This column MUST be of type String and MUST NOT contain null values. ## Column ID diff --git a/specification/columns/servicesubcategory.md b/specification/columns/servicesubcategory.md index f235967fb..8452e588b 100644 --- a/specification/columns/servicesubcategory.md +++ b/specification/columns/servicesubcategory.md @@ -4,7 +4,7 @@ The Service Subcategory is a secondary classification of the [Service Category]( The ServiceSubcategory column adheres to the following requirements: -* ServiceSubcategory is RECOMMENDED to be present in a FOCUS dataset and MUST NOT be null. +* ServiceSubcategory is RECOMMENDED to be present in a [*FOCUS dataset*](#glossary:FOCUS-dataset) and MUST NOT be null. * ServiceSubcategory is of type String and MUST be one of the allowed values. * Each ServiceSubcategory value MUST have one and only one parent ServiceCategory as specified in the allowed values below. * Though a given *service* can have multiple purposes, each *service* SHOULD have one and only one ServiceSubcategory that best aligns with its primary purpose. diff --git a/specification/columns/skuid.md b/specification/columns/skuid.md index 7ab6ce38d..584a54416 100644 --- a/specification/columns/skuid.md +++ b/specification/columns/skuid.md @@ -2,7 +2,7 @@ A SKU ID is a unique identifier that defines a provider-supported construct for organizing properties that are common across one or more [*SKU Prices*](#glossary:sku-price). SKU ID can be referenced on a catalog or [*price list*](#glossary:price-list) published by a provider to look up detailed information about the SKU. The composition of the properties associated with the SKU ID may differ across providers. Some providers may not support the [*SKU*](#glossary:sku) construct and instead associate all such properties directly with the *SKU Price*. SKU ID is commonly used for analyzing cost based on *SKU*-related properties above the pricing constructs. -The SkuId column MUST be present in a FOCUS dataset when the provider publishes a SKU list. This column MUST be of type String. It MUST NOT be null when [ChargeClass](#chargeclass) is not "Correction" and [ChargeCategory](#chargecategory) is "Usage" or "Purchase", MUST be null when ChargeCategory is "Tax", and MAY be null for all other combinations of ChargeClass and ChargeCategory. SkuId MUST equal SkuPriceId when a provider does not support an overarching SKU ID construct. +The SkuId column MUST be present in a [*FOCUS dataset*](#glossary:FOCUS-dataset) when the provider publishes a SKU list. This column MUST be of type String. It MUST NOT be null when [ChargeClass](#chargeclass) is not "Correction" and [ChargeCategory](#chargecategory) is "Usage" or "Purchase", MUST be null when ChargeCategory is "Tax", and MAY be null for all other combinations of ChargeClass and ChargeCategory. SkuId MUST equal SkuPriceId when a provider does not support an overarching SKU ID construct. ## Column ID diff --git a/specification/columns/skumeter.md b/specification/columns/skumeter.md index 6b642abe2..bdd892b9a 100644 --- a/specification/columns/skumeter.md +++ b/specification/columns/skumeter.md @@ -2,11 +2,11 @@ The SKU Meter describes the functionality being metered or measured by a particular SKU in a charge. -Providers often have billing models in which multiple SKUs exist for a given service to describe and bill for different functionalities for that service. For example, an object storage service may have separate SKUs for functionalities such as object storage, API requests, data transfer, encryption, and object management. This field helps practitioners understand which functionalities are being metered by the different SKUs that appear in a FOCUS dataset. +Providers often have billing models in which multiple SKUs exist for a given service to describe and bill for different functionalities for that service. For example, an object storage service may have separate SKUs for functionalities such as object storage, API requests, data transfer, encryption, and object management. This field helps practitioners understand which functionalities are being metered by the different SKUs that appear in a [*FOCUS dataset*](#glossary:FOCUS-dataset). The SkuMeter column adheres to the following requirements: -* SkuMeter MUST be present in the billing data when when the provider includes a [SkuId](#skuid). +* SkuMeter MUST be present in a *FOCUS dataset* when when the provider includes a [SkuId](#skuid). * SkuMeter MUST be of type String. * SkuMeter MUST be null when SkuId is null. * SkuMeter SHOULD NOT be null when SkuId is not null. diff --git a/specification/columns/subaccountid.md b/specification/columns/subaccountid.md index f0bfd2a4a..7ca7ccd62 100644 --- a/specification/columns/subaccountid.md +++ b/specification/columns/subaccountid.md @@ -2,7 +2,7 @@ A Sub Account ID is a provider-assigned identifier assigned to a [*sub account*](#glossary:sub-account). Sub Account ID is commonly used for scenarios like grouping based on organizational constructs, access management needs, and cost allocation strategies. -The SubAccountId column MUST be present in a FOCUS dataset when the provider supports a *sub account* construct. This column MUST be of type String. If a charge does not apply to a *sub account*, the SubAccountId column MUST be null. +The SubAccountId column MUST be present in a [*FOCUS dataset*](#glossary:FOCUS-dataset) when the provider supports a *sub account* construct. This column MUST be of type String. If a charge does not apply to a *sub account*, the SubAccountId column MUST be null. See [Appendix: Grouping constructs for resources or services](#groupingconstructsforresourcesorservices) for details and examples of the different grouping constructs supported by FOCUS. diff --git a/specification/columns/subaccountname.md b/specification/columns/subaccountname.md index 0f837ecec..b64f56fd6 100644 --- a/specification/columns/subaccountname.md +++ b/specification/columns/subaccountname.md @@ -2,7 +2,7 @@ A Sub Account Name is a display name assigned to a [*sub account*](#glossary:sub-account). Sub account Name is commonly used for scenarios like grouping based on organizational constructs, access management needs, and cost allocation strategies. -The SubAccountName column MUST be present in a FOCUS dataset when the provider supports a *sub account* construct. This column MUST be of type String. If a charge does not apply to a *sub account*, the SubAccountName column MUST be null. +The SubAccountName column MUST be present in a [*FOCUS dataset*](#glossary:FOCUS-dataset) when the provider supports a *sub account* construct. This column MUST be of type String. If a charge does not apply to a *sub account*, the SubAccountName column MUST be null. See [Appendix: Grouping constructs for resources or services](#groupingconstructsforresourcesorservices) for details and examples of the different grouping constructs supported by FOCUS. diff --git a/specification/columns/tags.md b/specification/columns/tags.md index 4a9c8039e..d273fa195 100644 --- a/specification/columns/tags.md +++ b/specification/columns/tags.md @@ -6,7 +6,7 @@ A tag becomes [*finalized*](#glossary:finalized-tag) when a single value is sele The Tags column adheres to the following requirements: -* The Tags column MUST be present in a FOCUS dataset when the provider supports setting user or provider-defined tags. +* The Tags column MUST be present in a [*FOCUS dataset*](#glossary:FOCUS-dataset) when the provider supports setting user or provider-defined tags. * The Tags column MUST contain user-defined and provider-defined tags. * The Tags column MUST only contain finalized tags. * The Tags column MUST be in [KeyValueFormat](#key-valueformat). diff --git a/specification/metadata/data_generator/datagenerator.md b/specification/metadata/data_generator/datagenerator.md index abc636b46..64ed31dca 100644 --- a/specification/metadata/data_generator/datagenerator.md +++ b/specification/metadata/data_generator/datagenerator.md @@ -2,7 +2,7 @@ Human-readable name of the entity that is generating the data. -The DataGenerator MUST be provided in the metadata. DataGenerator MUST be of type String and MUST NOT be null. The DataGenerator SHOULD be easily associated with the provider who generated the FOCUS dataset. +The DataGenerator MUST be provided in the metadata. DataGenerator MUST be of type String and MUST NOT be null. The DataGenerator SHOULD be easily associated with the provider who generated the [*FOCUS dataset*](#glossary:FOCUS-dataset). ## Metadata ID diff --git a/specification/metadata/metadata.mdpp b/specification/metadata/metadata.mdpp index 46a776168..128078fe5 100644 --- a/specification/metadata/metadata.mdpp +++ b/specification/metadata/metadata.mdpp @@ -1,6 +1,6 @@ # Metadata -The FOCUS specification defines a metadata structure to be supplied by data providers to facilitate practitioners' use of FOCUS data. This metadata includes general information about the data generator and the schema of the FOCUS dataset. +The FOCUS specification defines a metadata structure to be supplied by data providers to facilitate practitioners' use of FOCUS data. This metadata includes general information about the data generator and the schema of the [*FOCUS dataset*](#glossary:FOCUS-dataset). FOCUS Metadata SHOULD be provided in a format that is accessible programmatically, such as a file, website, API, or table. Providers SHOULD provide documentation on their implementation of the FOCUS metadata. diff --git a/specification/metadata/schema/column_definition/column_definition.mdpp b/specification/metadata/schema/column_definition/column_definition.mdpp index 18a2f8490..71ef1132e 100644 --- a/specification/metadata/schema/column_definition/column_definition.mdpp +++ b/specification/metadata/schema/column_definition/column_definition.mdpp @@ -1,6 +1,6 @@ # Column Definition -The FOCUS metadata schema column definition provides a list of the columns present in the FOCUS dataset along with metadata about the columns. +The FOCUS metadata schema column definition provides a list of the columns present in the [*FOCUS dataset*](#glossary:FOCUS-dataset) along with metadata about the columns. ## Requirements diff --git a/specification/metadata/schema/column_definition/columnname.md b/specification/metadata/schema/column_definition/columnname.md index bd6b40f96..0762433e9 100644 --- a/specification/metadata/schema/column_definition/columnname.md +++ b/specification/metadata/schema/column_definition/columnname.md @@ -1,6 +1,6 @@ # Column Name -The name of the column provided in the FOCUS dataset. +The name of the column provided in the [*FOCUS dataset*](#glossary:FOCUS-dataset). The ColumnName MUST be provided in the FOCUS Metadata schema. ColumnName MUST be of type String and MUST NOT contain null values. diff --git a/specification/metadata/schema/column_definition/datatype.md b/specification/metadata/schema/column_definition/datatype.md index 8a33adbca..bbd6b2eea 100644 --- a/specification/metadata/schema/column_definition/datatype.md +++ b/specification/metadata/schema/column_definition/datatype.md @@ -1,6 +1,6 @@ # Data Type -The data type of the column provided in the FOCUS dataset. +The data type of the column provided in the [*FOCUS dataset*](#glossary:FOCUS-dataset). The DataType MUST be provided in the FOCUS Metadata schema. DataType MUST be of type String and MUST NOT contain null values. diff --git a/specification/metadata/schema/column_definition/providertagprefixes.md b/specification/metadata/schema/column_definition/providertagprefixes.md index ca8ddb4b6..5fdfc278b 100644 --- a/specification/metadata/schema/column_definition/providertagprefixes.md +++ b/specification/metadata/schema/column_definition/providertagprefixes.md @@ -2,7 +2,7 @@ The Provider Tag Prefixes defines the list of prefixes used in the tag name of provider-defined [tags](#tags). This metadata is useful for the consumer to identify which tags are provider-defined vs user-defined. -The ProviderTagPrefixes MUST be provided when ColumnName is equal to Tags. The ProviderTagPrefix MUST be of type Array of Strings. The ProviderTagPrefixes SHOULD be easily associated with the provider who generated the FOCUS dataset. +The ProviderTagPrefixes MUST be provided when ColumnName is equal to Tags. The ProviderTagPrefix MUST be of type Array of Strings. The ProviderTagPrefixes SHOULD be easily associated with the provider who generated the [*FOCUS dataset*](#glossary:FOCUS-dataset). ## Metadata ID diff --git a/specification/metadata/schema/column_definition/stringencoding.md b/specification/metadata/schema/column_definition/stringencoding.md index 49f7fba22..ae790dee1 100644 --- a/specification/metadata/schema/column_definition/stringencoding.md +++ b/specification/metadata/schema/column_definition/stringencoding.md @@ -1,6 +1,6 @@ # String Encoding -The string encoding scheme of the column provided in the FOCUS dataset. +The string encoding scheme of the column provided in the [*FOCUS dataset*](#glossary:FOCUS-dataset). StringEncoding SHOULD be provided in the FOCUS Metadata schema when it is required to know this information in order to successfully read the data. StringEncoding MUST be of type String and MUST NOT contain null values. diff --git a/specification/metadata/schema/focusversion.md b/specification/metadata/schema/focusversion.md index 323b54428..0950e42a5 100644 --- a/specification/metadata/schema/focusversion.md +++ b/specification/metadata/schema/focusversion.md @@ -2,7 +2,7 @@ The version of FOCUS utilized for building the dataset. -The FocusVersion MUST be provided in the metadata. FocusVersion MUST be of type String and MUST NOT contain null values. FocusVersion MUST match one of the published versions of the FOCUS specification. FocusVersion MUST match the version of the FOCUS specification that the FOCUS dataset conforms to. +The FocusVersion MUST be provided in the metadata. FocusVersion MUST be of type String and MUST NOT contain null values. FocusVersion MUST match one of the published versions of the FOCUS specification. FocusVersion MUST match the version of the FOCUS specification that the [*FOCUS dataset*](#glossary:FOCUS-dataset) conforms to. ## Metadata ID diff --git a/specification/metadata/schema/providerversion.md b/specification/metadata/schema/providerversion.md index bcf3ebe6d..0b0c8450c 100644 --- a/specification/metadata/schema/providerversion.md +++ b/specification/metadata/schema/providerversion.md @@ -1,6 +1,6 @@ # Provider Version -The ProviderVersion MAY be supplied to declare the version of logic by which the FOCUS dataset was generated and is separate from FOCUS Version. ProviderVersion allows for the provider to specify changes that may not result in a structural change in the data. It is suggested that the provider version use a versioning approach such as [SemVer](https://semver.org) version. +The ProviderVersion MAY be supplied to declare the version of logic by which the [*FOCUS dataset*](#glossary:FOCUS-dataset) was generated and is separate from FOCUS Version. ProviderVersion allows for the provider to specify changes that may not result in a structural change in the data. It is suggested that the provider version use a versioning approach such as [SemVer](https://semver.org) version. ProviderVersion MUST be of type String and MUST NOT contain null values. If FocusVersion is changed a new ProviderVersion MUST be also changed. The provider MUST document what changes are present in the ProviderVersion. diff --git a/specification/metadata/schema/schema.mdpp b/specification/metadata/schema/schema.mdpp index 50825a4fe..8f40cc61b 100644 --- a/specification/metadata/schema/schema.mdpp +++ b/specification/metadata/schema/schema.mdpp @@ -8,7 +8,7 @@ The schema metadata object and its contents provides information about the struc FOCUS data artifacts, whether they are data files, data streams, or data tables, MUST provide a clear reference to the schema of the data. This reference MUST be retrievable without inspection of the contents of the FOCUS data within the data artifact. For some delivery mechanisms such as database tables, the provider may rely on the schema functionality of the providing system. -It is recommended that the schema reference be provided as an external reference rather than included in full as metadata accompanying the data artifact. This allows for easier understanding of when changes to the schema of the FOCUS datasets occurs. +It is recommended that the schema reference be provided as an external reference rather than included in full as metadata accompanying the data artifact. This allows for easier understanding of when changes to the schema of the [*FOCUS datasets*](#glossary:FOCUS-dataset) occurs. ### Schema Metadata Creation From ed909da0dd3bd12d5b0a0228509687ea8d03c6cf Mon Sep 17 00:00:00 2001 From: Joaquin Date: Thu, 10 Oct 2024 17:03:12 -0700 Subject: [PATCH 16/22] [EDITORIAL] Add Release v1.2 timeline (#584) This PR proposes the timeline for the development of FOCUS Release v1.2 --- RELEASE-PLANNING.md | 67 ++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 66 insertions(+), 1 deletion(-) diff --git a/RELEASE-PLANNING.md b/RELEASE-PLANNING.md index 2063999ad..043128d06 100644 --- a/RELEASE-PLANNING.md +++ b/RELEASE-PLANNING.md @@ -58,6 +58,71 @@ This section outlines the planned release schedule and key milestones for the FO +### Estimated Timeline for v1.2 +This table displays key milestones and dates related to the development of FOCUS Release v1.2 Specifications. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      DateMilestoneComment
      8-Oct-24Start Work Item PreparationFor Release v1.2, the group will implement a new process for creating Work Items.
      8-Oct-24 to 21-Nov-24Work Item CreationSix weeks (6) to develop the FOCUS Release (Rel) v1.2 scope.
      21-Nov-24 to 3-Apr-25Development PhaseNineteen weeks (19) to develop FOCUS Rel v1.2 specifications.
      23-Jan-25 to 6-Feb-25Interim Consistency ReviewTwo weeks (2) for the Interim Consistency Review of FOCUS Rel v1.2.
      3-Apr-25End Development PhaseEnd of FOCUS Rel v1.2 development.
      3-17-Apr-25Consistency ReviewTwo weeks (2) for the Final Consistency Review of FOCUS Rel v1.2.
      17-24-Apr-25Preparing baseline for IPR ReviewOne week (1) of preparation to start the IPR Review.
      24-April-25 to 24-May-25Start / End IPR Review v1.2During this 30-day period, members may exclude essential claims from their licensing commitments. Contact the FOCUS Executive Director.
      29-May-25WG Approval v1.2FOCUS Release Candidate v1.2 approved by the FOCUS members.
      29-May-25SC Ratification v1.2FOCUS Steering Committee ratifies Rel v1.2.
      3-Jun-25FinOpsX AnnouncementFOCUS Rel v1.2 must be ready for announcement sometime in June.
      + ### Estimated Timeline for v1.1 This table displays key milestones and dates related to the development of FOCUS Release v1.1. @@ -85,7 +150,7 @@ This table displays key milestones and dates related to the development of FOCUS - + From 8be09157c99c3a1db2d00aa42d339771024179bb Mon Sep 17 00:00:00 2001 From: Joaquin Date: Thu, 10 Oct 2024 20:15:14 -0700 Subject: [PATCH 17/22] Update feedback use case (#553) This PR suggests updating the current GitHub Issue "feedback" template. The proposed changes are aligned with the proposal [24.09.23 FOCUS Process Improvements](https://docs.google.com/document/d/1W10WbS3JzGio2zrWzytxkvvRigE8hBmfyCS9Vcx6wVw/edit?usp=sharing): * This proposal outlines improvements to the FOCUS Development Process, aligning it with best practices commonly adopted by standards organizations. While FOCUS has successfully implemented most lifecycle stages, the Work Item phase remains unaddressed. * The proposal aims to provide a clear starting point for group discussions, offering the following key recommendations: A structured process for Work Item creation. An improvement to the existing [FinOps Use Case Feedback]() (GitHub Issue) Enhancements to the Review & Approval process introduce a requirement that any objection must include a written rationale. --- .github/ISSUE_TEMPLATE/feedback.yml | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/feedback.yml b/.github/ISSUE_TEMPLATE/feedback.yml index 1ab51c5c0..656903ca8 100644 --- a/.github/ISSUE_TEMPLATE/feedback.yml +++ b/.github/ISSUE_TEMPLATE/feedback.yml @@ -1,14 +1,14 @@ -name: FinOps Use Case Feedback -description: Provide feedback on FinOps use cases that cannot be performed with the current FOCUS specification. +name: Feature Request and Use Case Feedback +description: Provide feedback on unsupported use cases or features in the FOCUS specification, including FinOps scenarios, to help prioritize updates. Avoid sharing proprietary information. title: "[FEEDBACK]: " -labels: [""] -assignees: ["mike-finopsorg,udam-f2"] +labels: ["use case"] +assignees: ["shawnalpay, jpradocueva,"] body: - type: markdown attributes: - value: "The FOCUS working group wants to understand what FinOps use cases cannot be performed today using the current specification so they can be prioritized for upcoming release. Please do not provide any information that may be considered Intellectual Property by any individual or organization." + value: "FOCUS working group seeks gaps in the current specification for FinOps and beyond. Share unsupported use cases or features to prioritize updates. Avoid sharing proprietary information." - - type: input + - type: textarea attributes: label: Proposed Change description: Short description of the change and why it is necessary. @@ -18,8 +18,8 @@ body: - type: textarea attributes: - label: What FinOps use cases cannot be performed without the proposed change? - description: Describe in detail the current FinOps use cases your organization cannot perform without the proposed change + label: What use cases, FinOps or others, can't be performed with the current specification without this change? + description: Describe in detail the use cases, whether FinOps-related or otherwise, that your organization cannot perform with the current specification without the proposed change. validations: required: true @@ -51,6 +51,14 @@ body: validations: required: true + - type: textarea + attributes: + label: Key Metrics and KPIs + description: List the metrics and KPIs that will measure the success of this use case (e.g., cost per service, spend reduction percentage). + placeholder: e.g., cost per service, spend reduction percentage, etc. + validations: + required: false + - type: textarea attributes: label: Context / Supporting information @@ -66,4 +74,3 @@ body: placeholder: Attach sample data or data extracts here. Ensure compliance with data privacy guidelines. validations: required: false - From c91200dc26fb7b911b31973b505d370774a5f3cb Mon Sep 17 00:00:00 2001 From: Joaquin Date: Mon, 14 Oct 2024 16:49:11 -0700 Subject: [PATCH 18/22] Add Shawn as a single assignee. Add Shawn as a single assignee. --- .github/ISSUE_TEMPLATE/discussion-topic.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/ISSUE_TEMPLATE/discussion-topic.yml b/.github/ISSUE_TEMPLATE/discussion-topic.yml index 04310627b..08d54d674 100644 --- a/.github/ISSUE_TEMPLATE/discussion-topic.yml +++ b/.github/ISSUE_TEMPLATE/discussion-topic.yml @@ -2,7 +2,7 @@ name: Discussion Topic description: Initiate discussion on broad topics within the FOCUS community. title: "[DISCUSSION]: " labels: ["discussion topic"] -assignees: ["mike-finopsorg,udam-f2"] +assignees: ["shawnalpay"] body: - type: textarea attributes: From 85d794991597eb08c2a1bfc182fd5c6677efeccc Mon Sep 17 00:00:00 2001 From: Joaquin Date: Mon, 14 Oct 2024 16:50:16 -0700 Subject: [PATCH 19/22] Update maintenance.yml Add Shawn as a single assignee. --- .github/ISSUE_TEMPLATE/maintenance.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/ISSUE_TEMPLATE/maintenance.yml b/.github/ISSUE_TEMPLATE/maintenance.yml index 3a39989ce..daae0715e 100644 --- a/.github/ISSUE_TEMPLATE/maintenance.yml +++ b/.github/ISSUE_TEMPLATE/maintenance.yml @@ -2,7 +2,7 @@ name: Maintenance Task description: Create tasks related to work on the GitHub Repository or GitHub Actions. title: "[MAINTENANCE]: " labels: ["repo maintenance"] -assignees: ["mike-finopsorg,udam-f2"] +assignees: ["shawnalpay"] body: - type: textarea attributes: From 4781ae0990ddab3291489e3e3873f1ce3bb1747e Mon Sep 17 00:00:00 2001 From: Joaquin Date: Mon, 14 Oct 2024 16:51:02 -0700 Subject: [PATCH 20/22] Update spec-change.yml Add Shawn as a single assignee. --- .github/ISSUE_TEMPLATE/spec-change.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/ISSUE_TEMPLATE/spec-change.yml b/.github/ISSUE_TEMPLATE/spec-change.yml index 344bdcc8c..aa4104c63 100644 --- a/.github/ISSUE_TEMPLATE/spec-change.yml +++ b/.github/ISSUE_TEMPLATE/spec-change.yml @@ -2,7 +2,7 @@ name: Spec Change description: Submit changes or updates to the current specification. title: "[SPEC CHANGE]: " labels: ["discussion topic"] -assignees: ["mike-finopsorg,udam-f2"] +assignees: ["shawnalpay"] body: - type: dropdown attributes: From c7abe9c6d0c062ae4b18073320858bdad9722230 Mon Sep 17 00:00:00 2001 From: Joaquin Date: Thu, 17 Oct 2024 12:05:22 -0700 Subject: [PATCH 21/22] New GitHub Issue template for Work Item Creation (#587) New GitHub Issue template to support Work Item Creation. --------- Co-authored-by: Shawn Alpay <77511110+shawnalpay@users.noreply.github.com> Co-authored-by: Christopher Harris --- .github/ISSUE_TEMPLATE/work-item.md | 53 ++++++++++++ .github/ISSUE_TEMPLATE/work-item.yml | 121 +++++++++++++++++++++++++++ 2 files changed, 174 insertions(+) create mode 100644 .github/ISSUE_TEMPLATE/work-item.md create mode 100644 .github/ISSUE_TEMPLATE/work-item.yml diff --git a/.github/ISSUE_TEMPLATE/work-item.md b/.github/ISSUE_TEMPLATE/work-item.md new file mode 100644 index 000000000..e8c3b7d2b --- /dev/null +++ b/.github/ISSUE_TEMPLATE/work-item.md @@ -0,0 +1,53 @@ +# Work Item Issue Template +description: +title: "[Work_Item]" +labels: ["work item"] +assignees: [shawnalpay, jpradocueva] + +### **Template Usage Notes**: +1. All fields marked as **mandatory** [*] must be filled before submission. While some datapoints are optional for the initial creation of the work item, all datapoints must be provided in order to be considered for spec development. +2. If you have suggestions for the specification but cannot fill out all fields in this issue template, please fill out a [Feedback] or [Discussion] issue template instead. +3. For **Supporting Documentation**, ensure that linked files are accessible to relevant stakeholders. + +--- + +## 1. **Problem Statement** * +Describe the problem, issue, use case, or opportunity that this work item addresses. +Include practitioner quotes illustrating real examples a) of questions being asked by practitioners and b) value unlocked by answering these questions, if available. +- **What is the problem?**: Explain the context and why it needs resolution. +- **Impact**: Describe how the problem affects users, systems, or the project. + +Your input ... + +## 2. **Objective** * +State the objective of this work item. What outcome is expected? +- **Success Criteria**: Define how success will be measured (e.g. metrics and KPIs). + +Your input ... + +## 3. **Supporting Documentation** * +Include links to supporting documents such as: +- Data Examples: [Link to data or relevant files; DO NOT share proprietary information] +- Related Use Cases or Discussion Documents: [Link to discussion] +- PRs or Other References: [Link to relevant references] + +Your input ... + +## 4. **Proposed Solution / Approach** +Outline any proposed solutions, approaches, or potential paths forward. Do not submit detailed solutions; please keep suggestions high-level. +- **Initial Ideas**: Describe potential solution paths, tools, or technologies. +- **Considerations**: Include any constraints, dependencies, or risks. +- **Feasibility**: Include any information that helps quantify feasibility, such as perceived level of effort to augment the spec, or existing fields in current data generator exports. +- **Benchmarks**: Are there established best practices for solving this problem available to practitioners today (e.g. mappings from existing CSP exports that are widely used)? + +Your input ... + +## 5. **Epic or Theme Association** +> This section will be completed by the Maintainers. +> - **Epic**: [Epic Name] +> - **Theme**: [Theme Name, if applicable] + +## 6. **Stakeholders** * +List the main stakeholders for this issue. +- **Primary Stakeholders**: [Name/Role] +- **Other Involved Parties**: [Names/Roles] diff --git a/.github/ISSUE_TEMPLATE/work-item.yml b/.github/ISSUE_TEMPLATE/work-item.yml new file mode 100644 index 000000000..bc422b790 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/work-item.yml @@ -0,0 +1,121 @@ +name: "Work Item Issue Template" +description: "Template for creating new work item issues" +title: "[Work_Item]" +labels: + - "work item" +assignees: + - "shawnalpay" + - "jpradocueva" +body: + - type: markdown + attributes: + value: | + --- + ### **Template Usage Notes**: + 1. All fields marked as **mandatory** [*] must be filled before submission. While some datapoints are optional for the initial creation of the work item, all datapoints must be provided in order to be considered for spec development. + 2. If you have suggestions for the specification but cannot fill out all fields in this issue template, please fill out a [Feedback] or [Discussion] issue template instead. + 3. For **Supporting Documentation**, ensure that linked files are accessible to relevant stakeholders. + + - type: markdown + attributes: + value: | + ## 1. **Problem Statement** + Describe the problem, issue, use case, or opportunity that this work item addresses. + Include practitioner quotes illustrating real examples a) of questions being asked by practitioners and b) value unlocked by answering these questions, if available. + - **What is the problem?**: Explain the context and why it needs resolution. + - **Impact**: Describe how the problem affects users, systems, or the project. + + - type: textarea + id: problem_statement + attributes: + label: "Problem Statement" + description: "Provide a detailed explanation of the problem or issue." + placeholder: "Your input here..." + value: "Provide details of the problem statement here." + validations: + required: true + + - type: markdown + attributes: + value: | + ## 2. **Objective** + State the objective of this work item. What outcome is expected? + - **Success Criteria**: Define how success will be measured (e.g. metrics and KPIs). + + - type: textarea + id: objective + attributes: + label: "Objective" + description: "Describe the expected outcome and success criteria." + placeholder: "Your input here..." + value: "Outline the expected outcome and success criteria." + validations: + required: true + + - type: markdown + attributes: + value: | + ## 3. **Supporting Documentation** + - Data Examples: [Link to data or relevant files; DO NOT share proprietary information] + - Related Use Cases or Discussion Documents: [Link to discussion] + - PRs or Other References: [Link to relevant references] + + - type: textarea + id: supporting_documentation + attributes: + label: "Supporting Documentation" + description: "Provide links to data examples, use cases, PRs, or other relevant documents." + placeholder: "Your input here..." + value: "Include links to supporting documentation, if applicable." + validations: + required: true + + - type: markdown + attributes: + value: | + ## 4. **Proposed Solution / Approach** + Outline any proposed solutions, approaches, or potential paths forward. Do not submit detailed solutions; please keep suggestions high-level. + - **Initial Ideas**: Describe potential solution paths, tools, or technologies. + - **Considerations**: Include any constraints, dependencies, or risks. + - **Feasibility**: Include any information that helps quantify feasibility, such as perceived level of effort to augment the spec, or existing fields in current data generator exports. + - **Benchmarks**: Are there established best practices for solving this problem available to practitioners today (e.g. mappings from existing CSP exports that are widely used)? + + - type: textarea + id: proposed_solution + attributes: + label: "Proposed Solution / Approach" + description: "Outline potential solutions or approaches." + placeholder: "Your input here..." + value: "Summarize the proposed solution or approach." + + - type: markdown + attributes: + value: | + ## 5. **Epic or Theme Association** + > This section will be completed by the Maintainers. + > - **Epic**: [Epic Name] + > - **Theme**: [Theme Name, if applicable] + + - type: textarea + id: epic_theme + attributes: + label: "Epic or Theme Association" + description: "Provide potential epics or themes" + placeholder: "Your input here..." + value: "Provide the rational for the Epic or Theme." + + - type: markdown + attributes: + value: | + ## 6. **Stakeholders** + List the main stakeholders for this issue. + - **Primary Stakeholder**: [Name/Role] + - **Other Involved Parties**: [Names/Roles] + + - type: textarea + id: stakeholders + attributes: + label: "Stakeholders" + description: "List the main stakeholders for this work item." + placeholder: "Your input here..." + value: "Provide names and roles of key stakeholders." From fbb9ddf9d9889a5fb794090c484d8b9ca4e55973 Mon Sep 17 00:00:00 2001 From: Joaquin Date: Thu, 17 Oct 2024 16:53:56 -0700 Subject: [PATCH 22/22] Editorial updates on column IDs and Display Names (#582) These changes won't affect the content in Release V1.1. They are actually editorial guidelines according to the working group agreement. --------- Co-authored-by: ijurica --- EDITORIAL_GUIDELINES.md | 73 ++++++++++++++++++++++++++--------------- 1 file changed, 46 insertions(+), 27 deletions(-) diff --git a/EDITORIAL_GUIDELINES.md b/EDITORIAL_GUIDELINES.md index 947acde16..29e7cbab1 100644 --- a/EDITORIAL_GUIDELINES.md +++ b/EDITORIAL_GUIDELINES.md @@ -3,7 +3,6 @@ The "Editorial Style Guidelines" section ensures consistency and clarity across These guidelines can be modified through a Pull Request (PR), which the members must review and agree upon. This process ensures that any changes are thoughtfully considered and maintains the overall integrity of our editorial standards. -
      CANCELED Two weeks Interim Consistency Review FOCUS Rel v1.1
      19-Sep-24 to 03-Oct-2419-Sep-24 to 08-Oct-24 Start / End of the FOCUS Rel v1.1 Final Consistency Review Two weeks Final Consistency Review FOCUS Rel v1.1
      @@ -12,27 +11,26 @@ These guidelines can be modified through a Pull Request (PR), which the members - + @@ -41,28 +39,44 @@ These guidelines can be modified through a Pull Request (PR), which the members + + + + + +
      ComponentEditorial Guidelines
      Column & Attribute Names:Column & Attribute Names: Column Names:
      - - Pricing Quantity
      - - Pricing Unit
      - - Provider

      + - Pricing Quantity
      + - Pricing Unit
      + - Provider

      Attribute Names:
      - - Currency Code Format
      - - Date/Time Format + - Currency Code Format
      + - Date/Time Format
      - Column Names:
      -    **Pricing Quantity**
      -    **Pricing Unit**
      -    **Provider**

      + Column Names:
      +    Pricing Quantity
      +    Pricing Unit
      +    Provider

      Attribute Names:
      -    **Currency Code Format**
      -    **Date/Time Format**
      +    Currency Code Format
      +    Date/Time Format
      - - Bold
      - Use the display name in the non-normative section.
      - The first occurrence in a section is linked to the section.
      Column & Attribute IDs: Columns IDs:
      - - PricingQuantity
      - - PricingUnit
      - - ProviderName

      + - PricingQuantity
      + - PricingUnit
      + - ProviderName

      Attributes IDs:
      - CurrencyCodeFormat
      - DateTimeFormat
      - Columns IDs::
      + Columns IDs:
         PricingQuantity
      -    PricingUnit
      -    ProviderName

      +    PricingUnit
      +    ProviderName

      Attributes IDs:
         CurrencyCodeFormat
         DateTimeFormat
      - - Use PascalCamel case (the first letter of every word, is capitalized) + - Use PascalCamel case (the first letter of every word, is capitalized)
      - Normal text without bold or italics.
      - The first occurrence in a section is linked to the section.
      Column Values: + - "Usage"
      + - "Tax"
      + - "TB"
      +
      + This column:
      +    * MUST be null when ChargeCategory is "Tax" ... +
      + - Enclosed in double quotation marks
      + - Normal text without bold or italics +
      Normative Keywords & Statements @@ -130,21 +144,26 @@ These guidelines can be modified through a Pull Request (PR), which the members * **Normative Requirements as a Bullet List**: Normative statements (those using Normative Keywords) should be written as bullet points instead of lengthy sentences. +* **Column IDs:** They SHOULD be used in normative text sections, such as when specifying mandatory rules, schema definitions, or other implementation-related content. These Column IDs should be formatted without spaces and should match the exact naming conventions used in the schema (e.g., CommitmentDiscountID). + +* **Display Names:** They SHOULD be used in introductory or explanatory sections where natural language context is more appropriate. In these sections, display names should follow normal text conventions, including spaces between words (e.g., Commitment Discount ID). + + ### Example > **2.28. Pricing Quantity** > -> The **[Pricing Quantity](#pricing-quantity)** represents the volume of a given [SKU](#glossary:sku) associated with a [resource](#glossary:resource) or [service](#glossary:service) used or purchased, based on the **[Pricing Unit](#pricing-unit)**. Distinct from **[Consumed Quantity](#consumed-quantity)** (complementary to **[Consumed Unit](#consumed-unit)**), it focuses on pricing and cost, not resource and service consumption. +> The Pricing Quantity represents the volume of a given SKU associated with a [*resource*](#glossary:resource) or [*service*](#glossary:service) used or purchased, based on the [Pricing Unit](#pricingunit). Distinct from [Consumed Quantity](#consumedquantity) (complementary to [Consumed Unit](#consumedunit)), it focuses on pricing and cost, not *resource* and *service* consumption. > > * The PricingQuantity column MUST be present in a [*FOCUS dataset*](#glossary:FOCUS-dataset). -> * This column MUST be of type Decimal and MUST conform to Numeric Format requirements. -> * The value MAY be negative in cases where ChargeClass is "Correction". +> * This column MUST be of type Decimal and MUST conform to [Numeric Format](#numericformat) requirements +> * The value MAY be negative in cases where [ChargeClass](#chargeclass) is "Correction". > > This column: -> * MUST NOT be null when ChargeClass is not "Correction" and ChargeCategory is "Usage" or "Purchase", +> * MUST NOT be null when [ChargeClass](#chargeclass) is not "Correction" and [ChargeCategory](#chargecategory) is "Usage" or "Purchase", > * MUST be null when ChargeCategory is "Tax", and > * MAY be null for all other combinations of ChargeClass and ChargeCategory. -> * When unit prices are not null, multiplying PricingQuantity by a unit price MUST produce a result equal to the corresponding cost metric, except in cases of ChargeClass "Correction", which may address PricingQuantity or any cost discrepancies independently. +> * When unit prices are not null, multiplying PricingQuantity by a unit price MUST produce a result equal to the corresponding cost metric, except in cases of ChargeClass "Correction", which may address PricingQuantity or any cost discrepancies independently. > > **2.28.1. Column ID** > @@ -156,7 +175,7 @@ These guidelines can be modified through a Pull Request (PR), which the members > > **2.28.3. Description** > -> The volume of a given SKU associated with a resource or service used or purchased, based on the Pricing Unit. +> The volume of a given SKU associated with a *resource* or *service* used or purchased, based on the Pricing Unit. > > **2.28.4. Content Constraints Constraint** >