Skip to content

Commit 534d9fc

Browse files
committed
feat: added custom fields for all new resources
1 parent e669a42 commit 534d9fc

File tree

31 files changed

+1201
-121
lines changed

31 files changed

+1201
-121
lines changed
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
kind: Added
2+
body: Added generic custom field support to all newer resources
3+
time: 2024-12-31T12:08:09.386099205+01:00

commercetools/custom_fields.go

Lines changed: 38 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ func CreateCustomFieldDraft(ctx context.Context, client *platform.ByProjectKeyRe
4343
return nil, err
4444
}
4545

46-
t, err := getTypeResource(ctx, client, d)
46+
t, err := getTypeResourceFromResourceData(ctx, client, d)
4747
if err != nil {
4848
return nil, err
4949
}
@@ -58,7 +58,10 @@ type SetCustomTypeAction interface {
5858
platform.ShippingMethodSetCustomTypeAction |
5959
platform.CustomerGroupSetCustomTypeAction |
6060
platform.DiscountCodeSetCustomTypeAction |
61-
platform.CartDiscountSetCustomTypeAction
61+
platform.CartDiscountSetCustomTypeAction |
62+
platform.AssociateRoleSetCustomTypeAction |
63+
platform.ProductSelectionSetCustomTypeAction |
64+
platform.BusinessUnitSetCustomTypeAction
6265
}
6366

6467
type SetCustomFieldAction interface {
@@ -68,10 +71,13 @@ type SetCustomFieldAction interface {
6871
platform.ShippingMethodSetCustomFieldAction |
6972
platform.CustomerGroupSetCustomFieldAction |
7073
platform.DiscountCodeSetCustomFieldAction |
71-
platform.CartDiscountSetCustomFieldAction
74+
platform.CartDiscountSetCustomFieldAction |
75+
platform.AssociateRoleSetCustomFieldAction |
76+
platform.ProductSelectionSetCustomFieldAction |
77+
platform.BusinessUnitSetCustomFieldAction
7278
}
7379

74-
func customFieldEncodeType(t *platform.Type, name string, value any) (any, error) {
80+
func CustomFieldEncodeType(t *platform.Type, name string, value any) (any, error) {
7581
// Suboptimal to do this everytime, however performance is not that important here and impact is negligible
7682
fieldTypes := map[string]platform.FieldType{}
7783
for _, field := range t.FieldDefinitions {
@@ -82,10 +88,10 @@ func customFieldEncodeType(t *platform.Type, name string, value any) (any, error
8288
if !ok {
8389
return nil, fmt.Errorf("no field '%s' defined in type %s (%s)", name, t.Key, t.ID)
8490
}
85-
return customFieldEncodeValue(fieldType, name, value)
91+
return CustomFieldEncodeValue(fieldType, name, value)
8692
}
8793

88-
func customFieldEncodeValue(t platform.FieldType, name string, value any) (any, error) {
94+
func CustomFieldEncodeValue(t platform.FieldType, name string, value any) (any, error) {
8995
switch v := t.(type) {
9096
case platform.CustomFieldLocalizedStringType:
9197
result := platform.LocalizedString{}
@@ -129,7 +135,7 @@ func customFieldEncodeValue(t platform.FieldType, name string, value any) (any,
129135
}
130136
element = string(marshalledValue)
131137
}
132-
itemValue, err := customFieldEncodeValue(v.ElementType, name, element)
138+
itemValue, err := CustomFieldEncodeValue(v.ElementType, name, element)
133139
if err != nil {
134140
return nil, err
135141
}
@@ -198,7 +204,7 @@ func CreateCustomFieldDraftRaw(data map[string]any, t *platform.Type) (*platform
198204
if raw, ok := data["fields"].(map[string]any); ok {
199205
container := platform.FieldContainer{}
200206
for key, value := range raw {
201-
enc, err := customFieldEncodeType(t, key, value)
207+
enc, err := CustomFieldEncodeType(t, key, value)
202208
if err != nil {
203209
return nil, err
204210
}
@@ -234,36 +240,40 @@ func flattenCustomFields(c *platform.CustomFields) []map[string]any {
234240
return []map[string]any{result}
235241
}
236242

237-
// getTypeResource returns the platform.Type for the type_id in the custom
238-
// field. The type_id is cached to minimize API calls when multiple resource
239-
// use the same type
240-
func getTypeResource(ctx context.Context, client *platform.ByProjectKeyRequestBuilder, d *schema.ResourceData) (*platform.Type, error) {
243+
func getTypeResourceFromResourceData(ctx context.Context, client *platform.ByProjectKeyRequestBuilder, d *schema.ResourceData) (*platform.Type, error) {
241244
custom := d.Get("custom")
242245
data := firstElementFromSlice(custom.([]any))
243246
if data == nil {
244247
return nil, nil
245248
}
246249

247250
if typeId, ok := data["type_id"].(string); ok {
248-
if cacheTypes == nil {
249-
cacheTypes = make(map[string]*platform.Type)
250-
}
251-
if t, exists := cacheTypes[typeId]; exists {
252-
if t == nil {
253-
return nil, fmt.Errorf("type %s not in cache due to previous error", typeId)
254-
}
255-
return t, nil
256-
}
257-
258-
t, err := client.Types().WithId(typeId).Get().Execute(ctx)
259-
cacheTypes[typeId] = t
260-
return t, err
251+
return GetTypeResource(ctx, client, typeId)
261252
}
262253
return nil, fmt.Errorf("missing type_id for custom fields")
263254
}
264255

256+
// GetTypeResource returns the platform.Type for the type_id in the custom
257+
// field. The type_id is cached to minimize API calls when multiple resource
258+
// use the same type
259+
func GetTypeResource(ctx context.Context, client *platform.ByProjectKeyRequestBuilder, typeId string) (*platform.Type, error) {
260+
if cacheTypes == nil {
261+
cacheTypes = make(map[string]*platform.Type)
262+
}
263+
if t, exists := cacheTypes[typeId]; exists {
264+
if t == nil {
265+
return nil, fmt.Errorf("type %s not in cache due to previous error", typeId)
266+
}
267+
return t, nil
268+
}
269+
270+
t, err := client.Types().WithId(typeId).Get().Execute(ctx)
271+
cacheTypes[typeId] = t
272+
return t, err
273+
}
274+
265275
func CustomFieldUpdateActions[T SetCustomTypeAction, F SetCustomFieldAction](ctx context.Context, client *platform.ByProjectKeyRequestBuilder, d *schema.ResourceData) ([]any, error) {
266-
t, err := getTypeResource(ctx, client, d)
276+
t, err := getTypeResourceFromResourceData(ctx, client, d)
267277
if err != nil {
268278
return nil, err
269279
}
@@ -294,7 +304,7 @@ func CustomFieldUpdateActions[T SetCustomTypeAction, F SetCustomFieldAction](ctx
294304
return []any{action}, nil
295305
}
296306

297-
changes := diffSlices(
307+
changes := DiffSlices(
298308
oldData["fields"].(map[string]any),
299309
newData["fields"].(map[string]any))
300310

@@ -306,7 +316,7 @@ func CustomFieldUpdateActions[T SetCustomTypeAction, F SetCustomFieldAction](ctx
306316
Value: nil,
307317
})
308318
} else {
309-
val, err := customFieldEncodeType(t, key, changes[key])
319+
val, err := CustomFieldEncodeType(t, key, changes[key])
310320
if err != nil {
311321
return nil, err
312322
}

commercetools/custom_fields_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ var customFieldEncodeValueTests = []struct {
6464
func TestCustomFieldEncodeValue(t *testing.T) {
6565
for _, tt := range customFieldEncodeValueTests {
6666
t.Run("TestCustomFieldEncodeValue", func(t *testing.T) {
67-
encodedValue, err := customFieldEncodeValue(tt.typ, "some_field", tt.value)
67+
encodedValue, err := CustomFieldEncodeValue(tt.typ, "some_field", tt.value)
6868
if tt.hasError {
6969
assert.Error(t, err)
7070
} else {

commercetools/utils.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -380,9 +380,9 @@ func removeValueFromSlice(items []string, value string) []string {
380380
return items
381381
}
382382

383-
// diffSlices does a diff on two slices and returns the changes. If a field is
383+
// DiffSlices does a diff on two slices and returns the changes. If a field is
384384
// no longer available then nil is returned.
385-
func diffSlices(old, new map[string]any) map[string]any {
385+
func DiffSlices(old, new map[string]any) map[string]any {
386386
result := map[string]any{}
387387
seen := map[string]bool{}
388388

docs/resources/associate_role.md

Lines changed: 40 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,31 @@ See also the [Associate Role API Documentation](https://docs.commercetools.com/a
1616
## Example Usage
1717

1818
```terraform
19-
resource "commercetools_associate_role" "regional_manager" {
20-
key = "regional-manager-europe"
19+
resource "commercetools_type" "my-type" {
20+
key = "my-type"
21+
name = {
22+
en = "My type"
23+
nl = "Mijn type"
24+
}
25+
26+
resource_type_ids = ["associate-role"]
27+
28+
field {
29+
name = "my-field"
30+
label = {
31+
en = "My field"
32+
nl = "Mijn veld"
33+
}
34+
type {
35+
name = "String"
36+
}
37+
}
38+
}
39+
40+
resource "commercetools_associate_role" "my-role" {
41+
key = "my-role"
2142
buyer_assignable = false
22-
name = "Regional Manager - Europe"
43+
name = "My Role"
2344
permissions = [
2445
"AddChildUnits",
2546
"UpdateAssociates",
@@ -61,6 +82,13 @@ resource "commercetools_associate_role" "regional_manager" {
6182
"UpdateApprovalRules",
6283
"UpdateApprovalFlows",
6384
]
85+
86+
custom {
87+
type_id = commercetools_type.my-type.id
88+
fields = {
89+
my_field = "My value"
90+
}
91+
}
6492
}
6593
```
6694

@@ -75,9 +103,18 @@ resource "commercetools_associate_role" "regional_manager" {
75103
### Optional
76104

77105
- `buyer_assignable` (Boolean) Whether the associate role can be assigned to an associate by a buyer. If false, the associate role can only be assigned using the general endpoint. Defaults to true.
106+
- `custom` (Block, Optional) Custom fields for this resource. (see [below for nested schema](#nestedblock--custom))
78107
- `name` (String) Name of the associate role.
79108

80109
### Read-Only
81110

82111
- `id` (String) Unique identifier of the associate role.
83112
- `version` (Number) Current version of the associate role.
113+
114+
<a id="nestedblock--custom"></a>
115+
### Nested Schema for `custom`
116+
117+
Optional:
118+
119+
- `fields` (Map of String) CustomValue fields for this resource. Note that the values need to be provided as JSON encoded strings: `my-value = jsonencode({"key": "value"})`
120+
- `type_id` (String) The ID of the custom type to use for this resource.

docs/resources/business_unit_company.md

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,27 @@ resource "commercetools_store" "my-store" {
2525
languages = ["en-GB"]
2626
}
2727
28+
resource "commercetools_type" "my-type" {
29+
key = "my-type"
30+
name = {
31+
en = "My type"
32+
nl = "Mijn type"
33+
}
34+
35+
resource_type_ids = ["business-unit"]
36+
37+
field {
38+
name = "my-field"
39+
label = {
40+
en = "My field"
41+
nl = "Mijn veld"
42+
}
43+
type {
44+
name = "String"
45+
}
46+
}
47+
}
48+
2849
resource "commercetools_business_unit_company" "my-company" {
2950
key = "my-company"
3051
name = "My company"
@@ -60,6 +81,13 @@ resource "commercetools_business_unit_company" "my-company" {
6081
shipping_address_keys = ["my-company-address-1", "my-company-address-2"]
6182
default_billing_address_key = "my-company-address-1"
6283
default_shipping_address_key = "my-company-address-1"
84+
85+
custom {
86+
type_id = commercetools_type.my-type.id
87+
fields = {
88+
my_field = "My value"
89+
}
90+
}
6391
}
6492
```
6593

@@ -76,6 +104,7 @@ resource "commercetools_business_unit_company" "my-company" {
76104
- `address` (Block List) Addresses used by the Business Unit. (see [below for nested schema](#nestedblock--address))
77105
- `billing_address_keys` (Set of String) Indexes of entries in addresses to set as billing addresses. The billingAddressIds of the [Customer](https://docs.commercetools.com/api/projects/customers) will be replaced by these addresses.
78106
- `contact_email` (String) The email address of the company.
107+
- `custom` (Block, Optional) Custom fields for this resource. (see [below for nested schema](#nestedblock--custom))
79108
- `default_billing_address_key` (String) Index of the entry in addresses to set as the default billing address.
80109
- `default_shipping_address_key` (String) Index of the entry in addresses to set as the default shipping address.
81110
- `shipping_address_keys` (Set of String) Indexes of entries in addresses to set as shipping addresses. The shippingAddressIds of the [Customer](https://docs.commercetools.com/api/projects/customers) will be replaced by these addresses.
@@ -129,6 +158,15 @@ Read-Only:
129158
- `id` (String) Unique identifier of the Address
130159

131160

161+
<a id="nestedblock--custom"></a>
162+
### Nested Schema for `custom`
163+
164+
Optional:
165+
166+
- `fields` (Map of String) CustomValue fields for this resource. Note that the values need to be provided as JSON encoded strings: `my-value = jsonencode({"key": "value"})`
167+
- `type_id` (String) The ID of the custom type to use for this resource.
168+
169+
132170
<a id="nestedblock--store"></a>
133171
### Nested Schema for `store`
134172

docs/resources/business_unit_division.md

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,27 @@ resource "commercetools_store" "my-store" {
2525
languages = ["en-GB"]
2626
}
2727
28+
resource "commercetools_type" "my-type" {
29+
key = "my-type"
30+
name = {
31+
en = "My type"
32+
nl = "Mijn type"
33+
}
34+
35+
resource_type_ids = ["business-unit"]
36+
37+
field {
38+
name = "my-field"
39+
label = {
40+
en = "My field"
41+
nl = "Mijn veld"
42+
}
43+
type {
44+
name = "String"
45+
}
46+
}
47+
}
48+
2849
resource "commercetools_business_unit_company" "my-company" {
2950
key = "my-company"
3051
name = "My company"
@@ -72,6 +93,13 @@ resource "commercetools_business_unit_division" "my-division" {
7293
shipping_address_keys = ["my-div-address-1", "my-div-address-2"]
7394
default_billing_address_key = "my-div-address-1"
7495
default_shipping_address_key = "my-div-address-1"
96+
97+
custom {
98+
type_id = commercetools_type.my-type.id
99+
fields = {
100+
my_field = "My value"
101+
}
102+
}
75103
}
76104
```
77105

@@ -90,6 +118,7 @@ resource "commercetools_business_unit_division" "my-division" {
90118
- `associate_mode` (String) Determines whether the business unit can inherit Associates from a parent. Defaults to `ExplicitAndFromParent`.
91119
- `billing_address_keys` (List of String) List of the billing addresses used by the division.
92120
- `contact_email` (String) The email address of the division.
121+
- `custom` (Block, Optional) Custom fields for this resource. (see [below for nested schema](#nestedblock--custom))
93122
- `default_billing_address_key` (String) Key of the default billing Address.
94123
- `default_shipping_address_key` (String) Key of the default shipping Address.
95124
- `parent_unit` (Block, Optional) Reference to a parent business unit by its key or id. One of either is required. (see [below for nested schema](#nestedblock--parent_unit))
@@ -145,6 +174,15 @@ Read-Only:
145174
- `id` (String) Unique identifier of the Address
146175

147176

177+
<a id="nestedblock--custom"></a>
178+
### Nested Schema for `custom`
179+
180+
Optional:
181+
182+
- `fields` (Map of String) CustomValue fields for this resource. Note that the values need to be provided as JSON encoded strings: `my-value = jsonencode({"key": "value"})`
183+
- `type_id` (String) The ID of the custom type to use for this resource.
184+
185+
148186
<a id="nestedblock--parent_unit"></a>
149187
### Nested Schema for `parent_unit`
150188

0 commit comments

Comments
 (0)