Repository: dbt-labs/dbt-core

Issue:
[CT-3013] [Bug] `non_additive_dimension` property `window_groupings` should be optional but isn't
### Is this a new bug in dbt-core?

- [X] I believe this is a new bug in dbt-core
- [X] I have searched the existing issues, and I could not find an existing issue for this bug

### Current Behavior

Currently if you specify a `measure` with a `non_additive_dimension` that doesn't have a `window_groupings` property you get an error. The work around is to specify an empty list, i.e. `window_groupings: []`

### Expected Behavior

No error should be raised if `window_groupings` isn't specified

### Steps To Reproduce

1. Add a non_additive_dimension measure to a semantic model
```yaml
semantic_models
  - name: your_semantic_model
  ...
  measures:
    - name: test_non_additive
       agg: sum
       expr: lifetime_spend_pretax
       non_additive_dimension:
         name: first_ordered_at
         window_choice: max
```
2. Run `dbt parse`
3. Get an error like the following
```
16:02:24  Encountered an error:
Parsing Error
  Invalid semantic_models config given in FilePath(searched_path='models', relative_path='marts/customers.yml', modification_time=1691182373.747098, project_root='/Users/quigleymalcolm/Developer/dbt-labs/jaffle-sl-template') @ semantic_models: {'name': 'your_semantic_model, 'defaults': {'agg_time_dimension': 'first_ordered_at'}, 'description': 'Customer grain mart.\n', 'model': "ref('customers')", 'entities': [{'name': 'customer', 'expr': 'customer_id', 'type': 'primary'}], 'dimensions': [{'name': 'customer_name', 'type': 'categorical'}, {'name': 'customer_type', 'type': 'categorical'}, {'name': 'first_ordered_at', 'type': 'time', 'type_params': {'time_granularity': 'day'}}, {'name': 'last_ordered_at', 'type': 'time', 'type_params': {'time_granularity': 'day'}}], 'measures': [{'name': 'count_lifetime_orders', 'description': 'Total count of orders per customer.', 'agg': 'sum'}, {'name': 'lifetime_spend_pretax', 'description': 'Customer lifetime spend before taxes.', 'agg': 'sum'}, {'name': 'lifetime_spend', 'agg': 'sum', 'description': 'Gross customer lifetime spend inclusive of taxes.'}, {'name': 'test_non_additive', 'agg': 'sum', 'expr': 'lifetime_spend_pretax', 'non_additive_dimension': {'name': 'customer_type', 'window_choice': 'max'}}]} - at path ['measures'][3]['non_additive_dimension']: {'name': 'customer_type', 'window_choice': 'max'} is not valid under any of the given schemas
```

### Relevant log output

```shell
See above
```


### Environment

```markdown
- OS: macOS Ventura 13.4.1
- Python: 3.8.10
- dbt: 1.6.0
```


### Which database adapter are you using with dbt?

snowflake

### Additional Context

_No response_


Discussion:

Resolving patch:
diff --git a/core/dbt/contracts/graph/unparsed.py b/core/dbt/contracts/graph/unparsed.py
--- a/core/dbt/contracts/graph/unparsed.py
+++ b/core/dbt/contracts/graph/unparsed.py
@@ -689,7 +689,7 @@ class UnparsedEntity(dbtClassMixin):
 class UnparsedNonAdditiveDimension(dbtClassMixin):
     name: str
     window_choice: str  # AggregationType enum
-    window_groupings: List[str]
+    window_groupings: List[str] = field(default_factory=list)
 
 
 @dataclass


Test patch:
diff --git a/tests/functional/semantic_models/test_semantic_model_parsing.py b/tests/functional/semantic_models/test_semantic_model_parsing.py
--- a/tests/functional/semantic_models/test_semantic_model_parsing.py
+++ b/tests/functional/semantic_models/test_semantic_model_parsing.py
@@ -50,6 +50,12 @@
         agg_time_dimension: ds
         agg_params:
           percentile: 0.99
+      - name: test_non_additive
+        expr: txn_revenue
+        agg: sum
+        non_additive_dimension:
+          name: ds
+          window_choice: max
 
     dimensions:
       - name: ds
@@ -125,7 +131,7 @@ def test_semantic_model_parsing(self, project):
             semantic_model.node_relation.relation_name
             == f'"dbt"."{project.test_schema}"."fct_revenue"'
         )
-        assert len(semantic_model.measures) == 5
+        assert len(semantic_model.measures) == 6
         # manifest should have one metric (that was created from a measure)
         assert len(manifest.metrics) == 2
         metric = manifest.metrics["metric.test.txn_revenue"]