diff --git a/src/pkg/services/m365/api/lists.go b/src/pkg/services/m365/api/lists.go index 35843a106d..4a5e76f91d 100644 --- a/src/pkg/services/m365/api/lists.go +++ b/src/pkg/services/m365/api/lists.go @@ -23,6 +23,7 @@ type columnDetails struct { createFieldName string getFieldName string isPersonColumn bool + isLookupColumn bool isMultipleEnabled bool hasDefaultedToText bool } @@ -420,6 +421,16 @@ func setColumnType( case orig.GetNumber() != nil: newColumn.SetNumber(orig.GetNumber()) case orig.GetLookup() != nil: + colDetails.isLookupColumn = true + isMultipleEnabled := ptr.Val(orig.GetLookup().GetAllowMultipleValues()) + colDetails.isMultipleEnabled = isMultipleEnabled + updatedName := colName + LookupIDFieldNamePart + colDetails.createFieldName = updatedName + + if !isMultipleEnabled { + colDetails.getFieldName = updatedName + } + newColumn.SetLookup(orig.GetLookup()) case orig.GetThumbnail() != nil: newColumn.SetThumbnail(orig.GetThumbnail()) @@ -540,7 +551,8 @@ func populateMultipleValues(val any, filteredData map[string]any, colDetails *co return } - if !colDetails.isPersonColumn { + if !colDetails.isPersonColumn && + !colDetails.isLookupColumn { return } @@ -550,11 +562,10 @@ func populateMultipleValues(val any, filteredData map[string]any, colDetails *co } lookupIDs := make([]float64, 0) - lookupKeys := []string{LookupIDKey, LookupValueKey, PersonEmailKey} for _, nestedFields := range multiNestedFields { md, ok := nestedFields.(map[string]any) - if !ok || !keys.HasKeys(md, lookupKeys...) { + if !ok || !keys.HasKeys(md, checkFields(colDetails)...) { continue } @@ -569,6 +580,17 @@ func populateMultipleValues(val any, filteredData map[string]any, colDetails *co filteredData[colDetails.createFieldName] = lookupIDs } +func checkFields(colDetails *columnDetails) []string { + switch { + case colDetails.isLookupColumn: + return []string{LookupIDKey, LookupValueKey} + case colDetails.isPersonColumn: + return []string{LookupIDKey, LookupValueKey, PersonEmailKey} + default: + return []string{} + } +} + // when creating list items with multiple values for a single column // we let the API know that we are sending a collection. // Hence this adds an additional field '@@odata.type' @@ -587,7 +609,7 @@ func specifyODataType(filteredData map[string]any, colDetails *columnDetails, co } switch { - case colDetails.isPersonColumn: + case colDetails.isPersonColumn, colDetails.isLookupColumn: filteredData[colName+ODataTypeFieldNamePart] = ODataTypeFieldNameIntVal default: filteredData[colName+ODataTypeFieldNamePart] = ODataTypeFieldNameStringVal diff --git a/src/pkg/services/m365/api/lists_test.go b/src/pkg/services/m365/api/lists_test.go index 2b07dbe712..d0d08f396a 100644 --- a/src/pkg/services/m365/api/lists_test.go +++ b/src/pkg/services/m365/api/lists_test.go @@ -288,6 +288,41 @@ func (suite *ListsUnitSuite) TestColumnDefinitionable_ColumnType() { colNames["pg-col"].createFieldName == "pg-colLookupId" }, }, + { + name: "lookup column, single value", + getOrig: func() models.ColumnDefinitionable { + lookupColumn := models.NewLookupColumn() + + cd := models.NewColumnDefinition() + cd.SetLookup(lookupColumn) + cd.SetName(ptr.To("refer-col")) + + return cd + }, + checkFn: func(cd models.ColumnDefinitionable, colNames map[string]*columnDetails) bool { + return cd.GetLookup() != nil && + colNames["refer-col"].getFieldName == "refer-colLookupId" && + colNames["refer-col"].createFieldName == "refer-colLookupId" + }, + }, + { + name: "lookup column, multiple value", + getOrig: func() models.ColumnDefinitionable { + lookupColumn := models.NewLookupColumn() + lookupColumn.SetAllowMultipleValues(ptr.To(true)) + + cd := models.NewColumnDefinition() + cd.SetLookup(lookupColumn) + cd.SetName(ptr.To("refer-col")) + + return cd + }, + checkFn: func(cd models.ColumnDefinitionable, colNames map[string]*columnDetails) bool { + return cd.GetLookup() != nil && + colNames["refer-col"].getFieldName == "refer-col" && + colNames["refer-col"].createFieldName == "refer-colLookupId" + }, + }, { name: "defaulted to text column", getOrig: func() models.ColumnDefinitionable { @@ -848,6 +883,51 @@ func (suite *ListsUnitSuite) TestSetAdditionalDataByColumnNames() { "PersonsLookupId@odata.type": "Collection(Edm.Int32)", }, }, + { + name: "lookup column, single value", + additionalData: map[string]any{ + "ReferLookupId": ptr.To(10), + }, + colDetails: map[string]*columnDetails{ + "Refer": { + isLookupColumn: true, + getFieldName: "ReferLookupId", + createFieldName: "ReferLookupId", + }, + }, + assertFn: assert.False, + expectedResult: map[string]any{ + "ReferLookupId": ptr.To(10), + }, + }, + { + name: "lookup column, multiple values", + additionalData: map[string]any{ + "Refers": []any{ + map[string]any{ + "LookupId": ptr.To(float64(10)), + "LookupValue": ptr.To("item-1"), + }, + map[string]any{ + "LookupId": ptr.To(float64(11)), + "LookupValue": ptr.To("item-1"), + }, + }, + }, + colDetails: map[string]*columnDetails{ + "Refers": { + isLookupColumn: true, + isMultipleEnabled: true, + getFieldName: "Refers", + createFieldName: "RefersLookupId", + }, + }, + assertFn: assert.True, + expectedResult: map[string]any{ + "RefersLookupId": []float64{10, 11}, + "RefersLookupId@odata.type": "Collection(Edm.Int32)", + }, + }, } for _, test := range tests { @@ -861,6 +941,34 @@ func (suite *ListsUnitSuite) TestSetAdditionalDataByColumnNames() { } } +func (suite *ListsUnitSuite) TestCheckFields() { + t := suite.T() + + tests := []struct { + name string + colDetails *columnDetails + expectedKeys []string + }{ + { + name: "lookup column", + colDetails: &columnDetails{isLookupColumn: true}, + expectedKeys: []string{LookupIDKey, LookupValueKey}, + }, + { + name: "person column", + colDetails: &columnDetails{isPersonColumn: true}, + expectedKeys: []string{LookupIDKey, LookupValueKey, PersonEmailKey}, + }, + } + + for _, test := range tests { + suite.Run(test.name, func() { + res := checkFields(test.colDetails) + assert.Equal(t, test.expectedKeys, res) + }) + } +} + type ListsAPIIntgSuite struct { tester.Suite its intgTesterSetup