Skip to content

Commit

Permalink
Merge pull request #498 from eclipse-tractusx/feat/orchestrator/clean…
Browse files Browse the repository at this point in the history
…ing-result-endpoint

Feat: Add Endpoint for Posting Cleaning Results to Orchestrator
  • Loading branch information
nicoprow authored Sep 28, 2023
2 parents 4cd3ac2 + 2e75c77 commit 86badee
Show file tree
Hide file tree
Showing 7 changed files with 469 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -100,4 +100,26 @@ interface CleaningTaskApi {
@PostMapping("/reservations")
@PostExchange("/reservations")
fun reserveCleaningTasks(@RequestBody reservationRequest: CleaningReservationRequest): CleaningReservationResponse

@Operation(
summary = "Post cleaning results for reserved cleaning tasks in given cleaning step",
description = "Post business partner cleaning results for the given cleaning tasks. " +
"In order to post a result for a cleaning task it needs to be reserved first, has to currently be in the given cleaning step and the time limit is not exceeded." +
"The number of results you can post at a time does not need to match the original number of reserved tasks." +
"Results are accepted via strategy 'all or nothing'." +
"For a single request, the maximum number of postable results is limited to \${bpdm.api.upsert-limit}."
)
@ApiResponses(
value = [
ApiResponse(
responseCode = "204",
description = "If the results could be processed"
),
ApiResponse(responseCode = "400", description = "On malformed task create requests or reaching upsert limit", content = [Content()]),
]
)
@Tag(name = "Cleaning Service")
@PostMapping("/results")
@PostExchange("/results")
fun resolveCleaningTasks(@RequestBody resultRequest: CleaningResultRequest)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/*******************************************************************************
* Copyright (c) 2021,2023 Contributors to the Eclipse Foundation
*
* See the NOTICE file(s) distributed with this work for additional
* information regarding copyright ownership.
*
* This program and the accompanying materials are made available under the
* terms of the Apache License, Version 2.0 which is available at
* https://www.apache.org/licenses/LICENSE-2.0.
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
* SPDX-License-Identifier: Apache-2.0
******************************************************************************/

package org.eclipse.tractusx.orchestrator.api.model

import io.swagger.v3.oas.annotations.media.ArraySchema
import io.swagger.v3.oas.annotations.media.Schema


@Schema(description = "A cleaning result for a cleaning task")
data class CleaningResultEntry(
@get:Schema(description = "The identifier of the cleaning task for which this is a result", required = true)
val taskId: String,
@get:Schema(description = "The actual result in form of business partner data. Maybe null if an error occurred during cleaning of this task.")
val result: BusinessPartnerFull? = null,
@get:ArraySchema(arraySchema = Schema(description = "Errors that occurred during cleaning of this task"))
val errors: List<TaskError> = emptyList()
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/*******************************************************************************
* Copyright (c) 2021,2023 Contributors to the Eclipse Foundation
*
* See the NOTICE file(s) distributed with this work for additional
* information regarding copyright ownership.
*
* This program and the accompanying materials are made available under the
* terms of the Apache License, Version 2.0 which is available at
* https://www.apache.org/licenses/LICENSE-2.0.
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
* SPDX-License-Identifier: Apache-2.0
******************************************************************************/

package org.eclipse.tractusx.orchestrator.api.model

import io.swagger.v3.oas.annotations.media.ArraySchema
import io.swagger.v3.oas.annotations.media.Schema

@Schema(description = "Request object for posting cleaning results")
data class CleaningResultRequest(
@get:ArraySchema(arraySchema = Schema(description = "The cleaning results for previously reserved cleaning tasks"))
val results: List<CleaningResultEntry>
)
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ package org.eclipse.tractusx.bpdm.orchestrator.controller

import org.eclipse.tractusx.bpdm.common.exception.BpdmUpsertLimitException
import org.eclipse.tractusx.bpdm.orchestrator.config.ApiConfigProperties
import org.eclipse.tractusx.bpdm.orchestrator.exception.BpdmEmptyResultException
import org.eclipse.tractusx.bpdm.orchestrator.util.DummyValues
import org.eclipse.tractusx.orchestrator.api.CleaningTaskApi
import org.eclipse.tractusx.orchestrator.api.model.*
Expand Down Expand Up @@ -52,6 +53,16 @@ class CleaningTaskController(
}
}

override fun resolveCleaningTasks(resultRequest: CleaningResultRequest) {
if (resultRequest.results.size > apiConfigProperties.upsertLimit)
throw BpdmUpsertLimitException(resultRequest.results.size, apiConfigProperties.upsertLimit)

resultRequest.results.forEach { resultEntry ->
if (resultEntry.result == null && resultEntry.errors.isEmpty())
throw BpdmEmptyResultException(resultEntry.taskId)
}
}


override fun searchCleaningTaskState(searchTaskIdRequest: TaskStateRequest): TaskStateResponse {
// ToDo: Replace with service logic
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/*******************************************************************************
* Copyright (c) 2021,2023 Contributors to the Eclipse Foundation
*
* See the NOTICE file(s) distributed with this work for additional
* information regarding copyright ownership.
*
* This program and the accompanying materials are made available under the
* terms of the Apache License, Version 2.0 which is available at
* https://www.apache.org/licenses/LICENSE-2.0.
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
* SPDX-License-Identifier: Apache-2.0
******************************************************************************/

package org.eclipse.tractusx.bpdm.orchestrator.exception

import org.springframework.http.HttpStatus
import org.springframework.web.bind.annotation.ResponseStatus


@ResponseStatus(HttpStatus.BAD_REQUEST)
class BpdmEmptyResultException(
taskId: String
) : RuntimeException("Result for cleaning task with ID '$taskId' is invalid as it does not contain resulting business partner data but also no errors.")
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,7 @@ import org.assertj.core.api.Assertions
import org.eclipse.tractusx.bpdm.orchestrator.util.BusinessPartnerTestValues
import org.eclipse.tractusx.bpdm.orchestrator.util.DummyValues
import org.eclipse.tractusx.orchestrator.api.client.OrchestrationApiClient
import org.eclipse.tractusx.orchestrator.api.model.CleaningReservationRequest
import org.eclipse.tractusx.orchestrator.api.model.CleaningStep
import org.eclipse.tractusx.orchestrator.api.model.TaskCreateRequest
import org.eclipse.tractusx.orchestrator.api.model.TaskMode
import org.eclipse.tractusx.orchestrator.api.model.TaskStateRequest
import org.eclipse.tractusx.orchestrator.api.model.*
import org.junit.jupiter.api.Test
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.test.context.SpringBootTest
Expand Down Expand Up @@ -107,6 +103,46 @@ class CleaningTaskControllerIT @Autowired constructor(
Assertions.assertThat(response).isEqualTo(expected)
}

/**
* Validate post cleaning result endpoint is invokable
*/
@Test
fun `post cleaning result is invokable`() {
val request = CleaningResultRequest(
results = listOf(
CleaningResultEntry(
taskId = "0",
result = BusinessPartnerFull(
generic = BusinessPartnerTestValues.businessPartner1,
legalEntity = BusinessPartnerTestValues.legalEntity1,
site = BusinessPartnerTestValues.site1,
address = BusinessPartnerTestValues.logisticAddress1
),
errors = emptyList()
),
CleaningResultEntry(
taskId = "1",
result = BusinessPartnerFull(
generic = BusinessPartnerTestValues.businessPartner2,
legalEntity = BusinessPartnerTestValues.legalEntity2,
site = BusinessPartnerTestValues.site2,
address = BusinessPartnerTestValues.logisticAddress2
),
errors = emptyList()
),
CleaningResultEntry(
taskId = "2",
result = null,
errors = listOf(
TaskError(type = TaskErrorType.Unspecified, "Error Description")
)
),
)
)

orchestratorClient.cleaningTasks.resolveCleaningTasks(request)
}

/**
* When requesting cleaning of too many business partners (over the upsert limit)
* Then throw exception
Expand Down Expand Up @@ -148,6 +184,34 @@ class CleaningTaskControllerIT @Autowired constructor(
}.isInstanceOf(WebClientResponseException::class.java)
}

/**
* When posting too many cleaning results (over the upsert limit)
* Then throw exception
*/
@Test
fun `expect exception on posting too many cleaning results`() {

val validCleaningResultEntry = CleaningResultEntry(
taskId = "0",
result = null,
errors = listOf(TaskError(type = TaskErrorType.Unspecified, description = "Description"))
)

//Create entries above the upsert limit of 3
val request = CleaningResultRequest(
results = listOf(
validCleaningResultEntry.copy(taskId = "0"),
validCleaningResultEntry.copy(taskId = "1"),
validCleaningResultEntry.copy(taskId = "2"),
validCleaningResultEntry.copy(taskId = "3"),
)
)

Assertions.assertThatThrownBy {
orchestratorClient.cleaningTasks.resolveCleaningTasks(request)
}.isInstanceOf(WebClientResponseException::class.java)
}

/**
* Search for taskId and get dummy response on the test
*/
Expand All @@ -167,4 +231,26 @@ class CleaningTaskControllerIT @Autowired constructor(
Assertions.assertThat(response).isEqualTo(expected)
}

/**
* When posting cleaning result without business partner data and no errors
* Then throw exception
*/
@Test
fun `expect exception on posting empty cleaning result`() {
val request = CleaningResultRequest(
results = listOf(
CleaningResultEntry(
taskId = "0",
result = null,
errors = emptyList()
)
)
)

Assertions.assertThatThrownBy {
orchestratorClient.cleaningTasks.resolveCleaningTasks(request)
}.isInstanceOf(WebClientResponseException::class.java)
}


}
Loading

0 comments on commit 86badee

Please sign in to comment.