diff --git a/bpdm-gate-api/src/main/kotlin/org/eclipse/tractusx/bpdm/gate/api/model/response/SharingStateDto.kt b/bpdm-gate-api/src/main/kotlin/org/eclipse/tractusx/bpdm/gate/api/model/response/SharingStateDto.kt
index 9fa452340..149e68a96 100644
--- a/bpdm-gate-api/src/main/kotlin/org/eclipse/tractusx/bpdm/gate/api/model/response/SharingStateDto.kt
+++ b/bpdm-gate-api/src/main/kotlin/org/eclipse/tractusx/bpdm/gate/api/model/response/SharingStateDto.kt
@@ -54,5 +54,8 @@ data class SharingStateDto(
val bpn: String? = null,
@get:Schema(description = "The date and time when the sharing process was started.")
- val sharingProcessStarted: LocalDateTime? = null
+ val sharingProcessStarted: LocalDateTime? = null,
+
+ @get:Schema(description = "The orchestrator task identifier that was created")
+ val taskId: String? = null,
)
diff --git a/bpdm-gate/pom.xml b/bpdm-gate/pom.xml
index f5a9a42e0..5efe1960e 100644
--- a/bpdm-gate/pom.xml
+++ b/bpdm-gate/pom.xml
@@ -152,6 +152,10 @@
spring-security-test
test
+
+ org.eclipse.tractusx
+ bpdm-orchestrator-api
+
diff --git a/bpdm-gate/src/main/kotlin/org/eclipse/tractusx/bpdm/gate/config/BpnConfigProperties.kt b/bpdm-gate/src/main/kotlin/org/eclipse/tractusx/bpdm/gate/config/BpnConfigProperties.kt
index 09ba0eb94..aad99a3c4 100644
--- a/bpdm-gate/src/main/kotlin/org/eclipse/tractusx/bpdm/gate/config/BpnConfigProperties.kt
+++ b/bpdm-gate/src/main/kotlin/org/eclipse/tractusx/bpdm/gate/config/BpnConfigProperties.kt
@@ -26,5 +26,6 @@ import org.springframework.boot.context.properties.ConfigurationProperties
data class BpnConfigProperties(
val agencyName: String = "Catena-X",
var name: String = "Business Partner Number",
- val id: String = "CX_BPN"
+ val id: String = "CX_BPN",
+ val ownerBpnL: String? = null
)
\ No newline at end of file
diff --git a/bpdm-gate/src/main/kotlin/org/eclipse/tractusx/bpdm/gate/config/OrchestratorClientConfig.kt b/bpdm-gate/src/main/kotlin/org/eclipse/tractusx/bpdm/gate/config/OrchestratorClientConfig.kt
new file mode 100644
index 000000000..971e24454
--- /dev/null
+++ b/bpdm-gate/src/main/kotlin/org/eclipse/tractusx/bpdm/gate/config/OrchestratorClientConfig.kt
@@ -0,0 +1,52 @@
+/*******************************************************************************
+ * 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.gate.config
+
+import org.eclipse.tractusx.orchestrator.api.client.OrchestrationApiClient
+import org.eclipse.tractusx.orchestrator.api.client.OrchestrationApiClientImpl
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty
+import org.springframework.context.annotation.Bean
+import org.springframework.context.annotation.Configuration
+import org.springframework.http.HttpHeaders
+import org.springframework.http.MediaType
+import org.springframework.web.reactive.function.client.WebClient
+
+
+@Configuration
+class OrchestratorClientConfig {
+
+ // Orchestrator-Client without authentication
+ @Bean
+ @ConditionalOnProperty(
+ value = ["bpdm.orchestrator.security-enabled"],
+ havingValue = "false",
+ matchIfMissing = true
+ )
+ fun orchestratorClientNoAuth(orchestratorConfigProperties: OrchestratorConfigProperties): OrchestrationApiClient {
+ val url = orchestratorConfigProperties.baseUrl
+ return OrchestrationApiClientImpl { webClientBuilder(url).build() }
+ }
+
+ private fun webClientBuilder(url: String) =
+ WebClient.builder()
+ .baseUrl(url)
+ .defaultHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
+
+}
\ No newline at end of file
diff --git a/bpdm-gate/src/main/kotlin/org/eclipse/tractusx/bpdm/gate/config/OrchestratorConfigProperties.kt b/bpdm-gate/src/main/kotlin/org/eclipse/tractusx/bpdm/gate/config/OrchestratorConfigProperties.kt
new file mode 100644
index 000000000..1ed241343
--- /dev/null
+++ b/bpdm-gate/src/main/kotlin/org/eclipse/tractusx/bpdm/gate/config/OrchestratorConfigProperties.kt
@@ -0,0 +1,28 @@
+/*******************************************************************************
+ * 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.gate.config
+
+import org.springframework.boot.context.properties.ConfigurationProperties
+
+
+@ConfigurationProperties(prefix = "bpdm.orchestrator")
+data class OrchestratorConfigProperties(
+ val baseUrl: String = "http://localhost:8085",
+)
diff --git a/bpdm-gate/src/main/kotlin/org/eclipse/tractusx/bpdm/gate/entity/SharingState.kt b/bpdm-gate/src/main/kotlin/org/eclipse/tractusx/bpdm/gate/entity/SharingState.kt
index a29e2a374..fa3bb5dfb 100644
--- a/bpdm-gate/src/main/kotlin/org/eclipse/tractusx/bpdm/gate/entity/SharingState.kt
+++ b/bpdm-gate/src/main/kotlin/org/eclipse/tractusx/bpdm/gate/entity/SharingState.kt
@@ -53,7 +53,10 @@ class SharingState(
var bpn: String? = null,
@Column(name = "sharing_process_started", nullable = true)
- var sharingProcessStarted: LocalDateTime? = null
+ var sharingProcessStarted: LocalDateTime? = null,
+
+ @Column(name = "task_id", nullable = true)
+ var taskId: String? = null
) : BaseEntity()
diff --git a/bpdm-gate/src/main/kotlin/org/eclipse/tractusx/bpdm/gate/service/BusinessPartnerMappings.kt b/bpdm-gate/src/main/kotlin/org/eclipse/tractusx/bpdm/gate/service/BusinessPartnerMappings.kt
index 3566e600a..362941083 100644
--- a/bpdm-gate/src/main/kotlin/org/eclipse/tractusx/bpdm/gate/service/BusinessPartnerMappings.kt
+++ b/bpdm-gate/src/main/kotlin/org/eclipse/tractusx/bpdm/gate/service/BusinessPartnerMappings.kt
@@ -187,6 +187,7 @@ class BusinessPartnerMappings {
door = dto.door
)
+
private fun toAlternativePostalAddressDto(entity: AlternativePostalAddress) =
AlternativePostalAddressGateDto(
geographicCoordinates = entity.geographicCoordinates?.let(::toGeoCoordinateDto),
@@ -211,6 +212,7 @@ class BusinessPartnerMappings {
deliveryServiceNumber = dto.deliveryServiceNumber
)
+
private fun toStreetDto(entity: Street) =
StreetGateDto(
name = entity.name,
@@ -223,6 +225,7 @@ class BusinessPartnerMappings {
additionalNameSuffix = entity.additionalNameSuffix
)
+
private fun toStreet(dto: StreetGateDto) =
Street(
name = dto.name,
@@ -256,6 +259,9 @@ class BusinessPartnerMappings {
private fun toGeoCoordinateDto(entity: GeographicCoordinate) =
GeoCoordinateDto(latitude = entity.latitude, longitude = entity.longitude, altitude = entity.altitude)
+
private fun toGeographicCoordinate(dto: GeoCoordinateDto) =
GeographicCoordinate(latitude = dto.latitude, longitude = dto.longitude, altitude = dto.altitude)
+
+
}
diff --git a/bpdm-gate/src/main/kotlin/org/eclipse/tractusx/bpdm/gate/service/BusinessPartnerService.kt b/bpdm-gate/src/main/kotlin/org/eclipse/tractusx/bpdm/gate/service/BusinessPartnerService.kt
index 4c0111cdf..97bd85d37 100644
--- a/bpdm-gate/src/main/kotlin/org/eclipse/tractusx/bpdm/gate/service/BusinessPartnerService.kt
+++ b/bpdm-gate/src/main/kotlin/org/eclipse/tractusx/bpdm/gate/service/BusinessPartnerService.kt
@@ -36,6 +36,8 @@ import org.eclipse.tractusx.bpdm.gate.entity.generic.*
import org.eclipse.tractusx.bpdm.gate.exception.BpdmMissingStageException
import org.eclipse.tractusx.bpdm.gate.repository.ChangelogRepository
import org.eclipse.tractusx.bpdm.gate.repository.generic.BusinessPartnerRepository
+import org.eclipse.tractusx.orchestrator.api.client.OrchestrationApiClient
+import org.eclipse.tractusx.orchestrator.api.model.*
import org.springframework.data.domain.Page
import org.springframework.data.domain.PageRequest
import org.springframework.stereotype.Service
@@ -46,7 +48,9 @@ class BusinessPartnerService(
private val businessPartnerRepository: BusinessPartnerRepository,
private val businessPartnerMappings: BusinessPartnerMappings,
private val sharingStateService: SharingStateService,
- private val changelogRepository: ChangelogRepository
+ private val changelogRepository: ChangelogRepository,
+ private val orchestrationApiClient: OrchestrationApiClient,
+ private val orchestratorMappings: OrchestratorMappings
) {
@Transactional
@@ -79,7 +83,16 @@ class BusinessPartnerService(
saveChangelog(resolutionResults)
val partners = resolutionResults.map { it.businessPartner }
- partners.forEach { entity -> initSharingState(entity) }
+ val orchestratorBusinessPartnersDto = resolutionResults.map { orchestratorMappings.toBusinessPartnerGenericDto(it.businessPartner) }
+ partners.forEach { entity ->
+ initSharingState(entity)
+ }
+
+ val taskCreateResponse = requestNewCleaning(orchestratorBusinessPartnersDto)
+
+ for (i in partners.indices) {
+ updateSharingState(partners[i], taskCreateResponse.createdTasks[i])
+ }
return businessPartnerRepository.saveAll(partners)
}
@@ -209,6 +222,24 @@ class BusinessPartnerService(
}
+ private fun requestNewCleaning(orchestratorBusinessPartnersDto: List): TaskCreateResponse {
+ return orchestrationApiClient.goldenRecordTasks.createTasks(
+ TaskCreateRequest(
+ TaskMode.UpdateFromSharingMember, orchestratorBusinessPartnersDto
+ )
+ )
+ }
+
+ private fun updateSharingState(entity: BusinessPartner, stateDto: TaskClientStateDto) {
+ sharingStateService.upsertSharingState(
+ SharingStateDto(
+ BusinessPartnerType.ADDRESS,
+ entity.externalId,
+ sharingStateType = orchestratorMappings.toSharingStateType(stateDto.processingState.resultState),
+ taskId = stateDto.taskId
+ )
+ )
+ }
}
diff --git a/bpdm-gate/src/main/kotlin/org/eclipse/tractusx/bpdm/gate/service/OrchestratorMappings.kt b/bpdm-gate/src/main/kotlin/org/eclipse/tractusx/bpdm/gate/service/OrchestratorMappings.kt
new file mode 100644
index 000000000..1f9064b9f
--- /dev/null
+++ b/bpdm-gate/src/main/kotlin/org/eclipse/tractusx/bpdm/gate/service/OrchestratorMappings.kt
@@ -0,0 +1,130 @@
+/*******************************************************************************
+ * 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.gate.service
+
+import mu.KotlinLogging
+import org.eclipse.tractusx.bpdm.common.dto.BusinessPartnerIdentifierDto
+import org.eclipse.tractusx.bpdm.common.dto.BusinessPartnerStateDto
+import org.eclipse.tractusx.bpdm.common.dto.ClassificationDto
+import org.eclipse.tractusx.bpdm.common.dto.GeoCoordinateDto
+import org.eclipse.tractusx.bpdm.gate.api.model.SharingStateType
+import org.eclipse.tractusx.bpdm.gate.config.BpnConfigProperties
+import org.eclipse.tractusx.bpdm.gate.entity.AlternativePostalAddress
+import org.eclipse.tractusx.bpdm.gate.entity.GeographicCoordinate
+import org.eclipse.tractusx.bpdm.gate.entity.PhysicalPostalAddress
+import org.eclipse.tractusx.bpdm.gate.entity.Street
+import org.eclipse.tractusx.bpdm.gate.entity.generic.*
+import org.eclipse.tractusx.orchestrator.api.model.*
+import org.springframework.stereotype.Service
+
+@Service
+class OrchestratorMappings(
+ private val bpnConfigProperties: BpnConfigProperties
+) {
+ private val logger = KotlinLogging.logger { }
+ fun toBusinessPartnerGenericDto(entity: BusinessPartner) = BusinessPartnerGenericDto(
+ nameParts = entity.nameParts,
+ shortName = entity.shortName,
+ identifiers = entity.identifiers.map { toIdentifierDto(it) },
+ legalForm = entity.legalForm,
+ states = entity.states.map { toStateDto(it) },
+ classifications = entity.classifications.map { toClassificationDto(it) },
+ roles = entity.roles,
+ postalAddress = toBusinessPartnerGenericPostalAddressDto(entity.postalAddress),
+ bpnL = entity.bpnL,
+ bpnS = entity.bpnS,
+ bpnA = entity.bpnA,
+ ownerBpnL = getOwnerBpnL(entity)
+ )
+
+ private fun toClassificationDto(entity: Classification) =
+ ClassificationDto(type = entity.type, code = entity.code, value = entity.value)
+
+ private fun toBusinessPartnerGenericPostalAddressDto(entity: PostalAddress) =
+ PostalAddressDto(
+ addressType = entity.addressType,
+ physicalPostalAddress = entity.physicalPostalAddress?.let(::toBusinessPartnerGenericPhysicalPostalAddressDto),
+ alternativePostalAddress = entity.alternativePostalAddress?.let(::toBusinessPartnerGenericAlternativePostalAddressDto)
+ )
+
+ private fun toBusinessPartnerGenericPhysicalPostalAddressDto(entity: PhysicalPostalAddress) =
+ PhysicalPostalAddressDto(
+ geographicCoordinates = entity.geographicCoordinates?.let(::toBusinessPartnerGenericGeoCoordinateDto),
+ country = entity.country,
+ administrativeAreaLevel1 = entity.administrativeAreaLevel1,
+ administrativeAreaLevel2 = entity.administrativeAreaLevel2,
+ administrativeAreaLevel3 = entity.administrativeAreaLevel3,
+ postalCode = entity.postalCode,
+ city = entity.city,
+ district = entity.district,
+ street = entity.street?.let(::toGenericBusinessPartnerStreetDto),
+ companyPostalCode = entity.companyPostalCode,
+ industrialZone = entity.industrialZone,
+ building = entity.building,
+ floor = entity.floor,
+ door = entity.door
+ )
+
+ private fun toBusinessPartnerGenericAlternativePostalAddressDto(entity: AlternativePostalAddress): AlternativePostalAddressDto =
+ AlternativePostalAddressDto(
+ geographicCoordinates = entity.geographicCoordinates?.let(::toBusinessPartnerGenericGeoCoordinateDto),
+ country = entity.country,
+ administrativeAreaLevel1 = entity.administrativeAreaLevel1,
+ postalCode = entity.postalCode,
+ city = entity.city,
+ deliveryServiceType = entity.deliveryServiceType,
+ deliveryServiceQualifier = entity.deliveryServiceQualifier,
+ deliveryServiceNumber = entity.deliveryServiceNumber
+ )
+
+ private fun toGenericBusinessPartnerStreetDto(entity: Street) =
+ StreetDto(
+ name = entity.name,
+ houseNumber = entity.houseNumber,
+ milestone = entity.milestone,
+ direction = entity.direction,
+ namePrefix = entity.namePrefix,
+ additionalNamePrefix = entity.additionalNamePrefix,
+ nameSuffix = entity.nameSuffix,
+ additionalNameSuffix = entity.additionalNameSuffix
+ )
+
+ private fun toStateDto(entity: State) =
+ BusinessPartnerStateDto(type = entity.type, validFrom = entity.validFrom, validTo = entity.validTo, description = entity.description)
+
+ private fun toIdentifierDto(entity: Identifier) =
+ BusinessPartnerIdentifierDto(type = entity.type, value = entity.value, issuingBody = entity.issuingBody)
+
+ private fun toBusinessPartnerGenericGeoCoordinateDto(entity: GeographicCoordinate) =
+ GeoCoordinateDto(latitude = entity.latitude, longitude = entity.longitude, altitude = entity.altitude)
+
+ private fun getOwnerBpnL(entity: BusinessPartner): String? {
+ return if (entity.isOwnCompanyData) bpnConfigProperties.ownerBpnL else {
+ logger.warn { "Owner BPNL property is not configured" }
+ null
+ }
+ }
+
+ fun toSharingStateType(resultState: ResultState) = when (resultState) {
+ ResultState.Pending -> SharingStateType.Pending
+ ResultState.Success -> SharingStateType.Success
+ ResultState.Error -> SharingStateType.Error
+ }
+}
\ No newline at end of file
diff --git a/bpdm-gate/src/main/kotlin/org/eclipse/tractusx/bpdm/gate/service/SharingStateService.kt b/bpdm-gate/src/main/kotlin/org/eclipse/tractusx/bpdm/gate/service/SharingStateService.kt
index a02a961fe..a58d4d574 100644
--- a/bpdm-gate/src/main/kotlin/org/eclipse/tractusx/bpdm/gate/service/SharingStateService.kt
+++ b/bpdm-gate/src/main/kotlin/org/eclipse/tractusx/bpdm/gate/service/SharingStateService.kt
@@ -54,7 +54,8 @@ class SharingStateService(private val stateRepository: SharingStateRepository) {
sharingErrorCode = dto.sharingErrorCode,
sharingErrorMessage = dto.sharingErrorMessage,
bpn = dto.bpn,
- sharingProcessStarted = dto.sharingProcessStarted
+ sharingProcessStarted = dto.sharingProcessStarted,
+ taskId = dto.taskId
)
)
}
@@ -65,10 +66,10 @@ class SharingStateService(private val stateRepository: SharingStateRepository) {
entity.sharingErrorCode = dto.sharingErrorCode
entity.sharingErrorMessage = dto.sharingErrorMessage
entity.bpn = dto.bpn
+ entity.taskId = dto.taskId
if (dto.sharingProcessStarted != null) {
entity.sharingProcessStarted = dto.sharingProcessStarted
}
-
this.stateRepository.save(entity)
}
@@ -90,7 +91,8 @@ class SharingStateService(private val stateRepository: SharingStateRepository) {
sharingErrorCode = it.sharingErrorCode,
sharingErrorMessage = it.sharingErrorMessage,
bpn = it.bpn,
- sharingProcessStarted = it.sharingProcessStarted
+ sharingProcessStarted = it.sharingProcessStarted,
+ taskId = it.taskId
)
})
diff --git a/bpdm-gate/src/main/resources/application.properties b/bpdm-gate/src/main/resources/application.properties
index f8dc76597..e1e65a3ce 100644
--- a/bpdm-gate/src/main/resources/application.properties
+++ b/bpdm-gate/src/main/resources/application.properties
@@ -28,6 +28,7 @@ bpdm.api.upsert-limit=100
bpdm.bpn.agency-name=Catena-X
bpdm.bpn.name=Business Partner Number
bpdm.bpn.id=CX_BPN
+bpdm.bpn.owner-bpn-l=# Insert owner BPNL here
#Springdoc swagger configuration
springdoc.swagger-ui.disable-swagger-default-url=true
springdoc.swagger-ui.path=/ui/swagger-ui
@@ -42,6 +43,8 @@ management.health.readinessState.enabled=true
# No auth on default
bpdm.gate-security.pool-security-enabled=false
bpdm.pool.base-url=http://localhost:8080/api/catena
+bpdm.orchestrator.security-enabled=false
+bpdm.orchestrator.base-url=http://localhost:8085
#No security on default
bpdm.security.enabled=false
#Datasource configuration
diff --git a/bpdm-gate/src/main/resources/db/migration/V4_0_0_17__add_cleaning_task_id_sharing_states.sql b/bpdm-gate/src/main/resources/db/migration/V4_0_0_17__add_cleaning_task_id_sharing_states.sql
new file mode 100644
index 000000000..e83e449eb
--- /dev/null
+++ b/bpdm-gate/src/main/resources/db/migration/V4_0_0_17__add_cleaning_task_id_sharing_states.sql
@@ -0,0 +1,2 @@
+ALTER TABLE sharing_states
+ADD COLUMN task_id VARCHAR(255);
\ No newline at end of file
diff --git a/bpdm-gate/src/test/kotlin/org/eclipse/tractusx/bpdm/gate/controller/BusinessPartnerControllerIT.kt b/bpdm-gate/src/test/kotlin/org/eclipse/tractusx/bpdm/gate/controller/BusinessPartnerControllerIT.kt
index f9efcc9cf..c7dd6e1a6 100644
--- a/bpdm-gate/src/test/kotlin/org/eclipse/tractusx/bpdm/gate/controller/BusinessPartnerControllerIT.kt
+++ b/bpdm-gate/src/test/kotlin/org/eclipse/tractusx/bpdm/gate/controller/BusinessPartnerControllerIT.kt
@@ -19,26 +19,37 @@
package org.eclipse.tractusx.bpdm.gate.controller
+import com.fasterxml.jackson.databind.ObjectMapper
+import com.github.tomakehurst.wiremock.client.WireMock
+import com.github.tomakehurst.wiremock.core.WireMockConfiguration
+import com.github.tomakehurst.wiremock.junit5.WireMockExtension
import org.assertj.core.api.Assertions
import org.eclipse.tractusx.bpdm.common.dto.BusinessPartnerIdentifierDto
import org.eclipse.tractusx.bpdm.common.dto.BusinessPartnerStateDto
+import org.eclipse.tractusx.bpdm.common.dto.BusinessPartnerType
import org.eclipse.tractusx.bpdm.common.dto.ClassificationDto
import org.eclipse.tractusx.bpdm.common.dto.request.PaginationRequest
import org.eclipse.tractusx.bpdm.gate.api.client.GateClient
+import org.eclipse.tractusx.bpdm.gate.api.model.SharingStateType
import org.eclipse.tractusx.bpdm.gate.api.model.request.BusinessPartnerInputRequest
import org.eclipse.tractusx.bpdm.gate.api.model.response.BusinessPartnerInputDto
+import org.eclipse.tractusx.bpdm.gate.api.model.response.SharingStateDto
import org.eclipse.tractusx.bpdm.gate.util.BusinessPartnerNonVerboseValues
import org.eclipse.tractusx.bpdm.gate.util.BusinessPartnerVerboseValues
import org.eclipse.tractusx.bpdm.gate.util.DbTestHelpers
import org.eclipse.tractusx.bpdm.gate.util.PostgreSQLContextInitializer
+import org.eclipse.tractusx.orchestrator.api.model.*
import org.junit.jupiter.api.Assertions.assertEquals
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Test
+import org.junit.jupiter.api.extension.RegisterExtension
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.test.context.SpringBootTest
import org.springframework.http.HttpStatus
import org.springframework.test.context.ActiveProfiles
import org.springframework.test.context.ContextConfiguration
+import org.springframework.test.context.DynamicPropertyRegistry
+import org.springframework.test.context.DynamicPropertySource
import org.springframework.web.reactive.function.client.WebClientResponseException
import java.time.Instant
@@ -51,15 +62,35 @@ import java.time.Instant
class BusinessPartnerControllerIT @Autowired constructor(
val testHelpers: DbTestHelpers,
val gateClient: GateClient,
+ val objectMapper: ObjectMapper
) {
+ companion object {
+ const val ORCHESTRATOR_REQUEST_NEW_CLEANING = "/api/golden-record-tasks"
+
+ @JvmField
+ @RegisterExtension
+ val gateWireMockServer: WireMockExtension = WireMockExtension.newInstance()
+ .options(WireMockConfiguration.wireMockConfig().dynamicPort())
+ .build()
+
+ @JvmStatic
+ @DynamicPropertySource
+ fun properties(registry: DynamicPropertyRegistry) {
+ registry.add("bpdm.orchestrator.base-url") { gateWireMockServer.baseUrl() }
+ }
+ }
@BeforeEach
fun beforeEach() {
testHelpers.truncateDbTables()
+ gateWireMockServer.resetAll()
+ this.mockOrchestratorApi()
}
@Test
fun `insert minimal business partner`() {
+
+
val upsertRequests = listOf(BusinessPartnerNonVerboseValues.bpInputRequestMinimal)
val upsertResponses = gateClient.businessParters.upsertBusinessPartnersInput(upsertRequests).body!!
assertUpsertResponsesMatchRequests(upsertResponses, upsertRequests)
@@ -71,7 +102,11 @@ class BusinessPartnerControllerIT @Autowired constructor(
@Test
fun `insert three business partners`() {
- val upsertRequests = listOf(BusinessPartnerNonVerboseValues.bpInputRequestFull, BusinessPartnerNonVerboseValues.bpInputRequestMinimal, BusinessPartnerNonVerboseValues.bpInputRequestChina)
+ val upsertRequests = listOf(
+ BusinessPartnerNonVerboseValues.bpInputRequestFull,
+ BusinessPartnerNonVerboseValues.bpInputRequestMinimal,
+ BusinessPartnerNonVerboseValues.bpInputRequestChina
+ )
val upsertResponses = gateClient.businessParters.upsertBusinessPartnersInput(upsertRequests).body!!
assertUpsertResponsesMatchRequests(upsertResponses, upsertRequests)
@@ -80,8 +115,63 @@ class BusinessPartnerControllerIT @Autowired constructor(
testHelpers.assertRecursively(searchResponsePage.content).isEqualTo(upsertResponses)
}
+ @Test
+ fun `insert three business partners and check sharing state is pending and has taskid`() {
+ val upsertRequests = listOf(
+ BusinessPartnerNonVerboseValues.bpInputRequestFull,
+ BusinessPartnerNonVerboseValues.bpInputRequestMinimal,
+ BusinessPartnerNonVerboseValues.bpInputRequestChina
+ )
+ gateClient.businessParters.upsertBusinessPartnersInput(upsertRequests).body!!
+ val upsertExternalIds = listOf(
+ BusinessPartnerNonVerboseValues.bpInputRequestFull.externalId,
+ BusinessPartnerNonVerboseValues.bpInputRequestMinimal.externalId,
+ BusinessPartnerNonVerboseValues.bpInputRequestChina.externalId
+ )
+ val upsertSharingStatesRequests = listOf(
+ SharingStateDto(
+ businessPartnerType = BusinessPartnerType.ADDRESS,
+ externalId = "external-1",
+ sharingStateType = SharingStateType.Pending,
+ sharingErrorCode = null,
+ sharingErrorMessage = null,
+ bpn = null,
+ sharingProcessStarted = null,
+ taskId = "0"
+ ),
+ SharingStateDto(
+ businessPartnerType = BusinessPartnerType.ADDRESS,
+ externalId = "external-2",
+ sharingStateType = SharingStateType.Pending,
+ sharingErrorCode = null,
+ sharingErrorMessage = null,
+ bpn = null,
+ sharingProcessStarted = null,
+ taskId = "1"
+ ),
+ SharingStateDto(
+ businessPartnerType = BusinessPartnerType.ADDRESS,
+ externalId = "external-3",
+ sharingStateType = SharingStateType.Pending,
+ sharingErrorCode = null,
+ sharingErrorMessage = null,
+ bpn = null,
+ sharingProcessStarted = null,
+ taskId = "2"
+ )
+ )
+
+ val upsertSharingStateResponses = readSharingStates(BusinessPartnerType.ADDRESS, upsertExternalIds)
+
+
+ testHelpers.assertRecursively(upsertSharingStateResponses).isEqualTo(upsertSharingStatesRequests)
+
+ }
+
+
@Test
fun `insert and then update business partner`() {
+
val insertRequests = listOf(BusinessPartnerNonVerboseValues.bpInputRequestMinimal)
val externalId = insertRequests.first().externalId
val insertResponses = gateClient.businessParters.upsertBusinessPartnersInput(insertRequests).body!!
@@ -138,7 +228,8 @@ class BusinessPartnerControllerIT @Autowired constructor(
)
gateClient.businessParters.upsertBusinessPartnersInput(upsertRequests)
- val searchResponsePage = gateClient.businessParters.getBusinessPartnersInput(listOf(BusinessPartnerVerboseValues.externalId1, BusinessPartnerVerboseValues.externalId3))
+ val searchResponsePage =
+ gateClient.businessParters.getBusinessPartnersInput(listOf(BusinessPartnerVerboseValues.externalId1, BusinessPartnerVerboseValues.externalId3))
assertUpsertResponsesMatchRequests(searchResponsePage.content, listOf(upsertRequests[0], upsertRequests[2]))
}
@@ -152,14 +243,18 @@ class BusinessPartnerControllerIT @Autowired constructor(
gateClient.businessParters.upsertBusinessPartnersInput(upsertRequests)
// missing externalIds are just ignored in the response
- val searchResponsePage = gateClient.businessParters.getBusinessPartnersInput(listOf(BusinessPartnerVerboseValues.externalId2, BusinessPartnerVerboseValues.externalId4))
+ val searchResponsePage =
+ gateClient.businessParters.getBusinessPartnersInput(listOf(BusinessPartnerVerboseValues.externalId2, BusinessPartnerVerboseValues.externalId4))
assertUpsertResponsesMatchRequests(searchResponsePage.content, listOf(upsertRequests[1]))
}
@Test
fun `query business partners using paging`() {
val upsertRequests = listOf(
- BusinessPartnerNonVerboseValues.bpInputRequestFull.copy(externalId = BusinessPartnerNonVerboseValues.bpInputRequestFull.externalId, shortName = "1"),
+ BusinessPartnerNonVerboseValues.bpInputRequestFull.copy(
+ externalId = BusinessPartnerNonVerboseValues.bpInputRequestFull.externalId,
+ shortName = "1"
+ ),
BusinessPartnerNonVerboseValues.bpInputRequestMinimal.copy(externalId = BusinessPartnerVerboseValues.externalId2, shortName = "2"),
BusinessPartnerNonVerboseValues.bpInputRequestMinimal.copy(externalId = BusinessPartnerVerboseValues.externalId3, shortName = "3")
)
@@ -224,4 +319,74 @@ class BusinessPartnerControllerIT @Autowired constructor(
ClassificationDto::code,
ClassificationDto::value
)
+
+ private fun mockOrchestratorApi() {
+ val responseOrchestratorTaskResponse =
+ TaskCreateResponse(
+ listOf(
+ TaskClientStateDto(
+ taskId = "0",
+ businessPartnerResult = null,
+ processingState = TaskProcessingStateDto(
+ resultState = ResultState.Pending,
+ step = TaskStep.CleanAndSync,
+ stepState = StepState.Queued,
+ errors = emptyList(),
+ createdAt = Instant.now(),
+ modifiedAt = Instant.now()
+ )
+ ),
+ TaskClientStateDto(
+ taskId = "1",
+ businessPartnerResult = null,
+ processingState = TaskProcessingStateDto(
+ resultState = ResultState.Pending,
+ step = TaskStep.CleanAndSync,
+ stepState = StepState.Queued,
+ errors = emptyList(),
+ createdAt = Instant.now(),
+ modifiedAt = Instant.now()
+ )
+ ),
+ TaskClientStateDto(
+ taskId = "2",
+ businessPartnerResult = null,
+ processingState = TaskProcessingStateDto(
+ resultState = ResultState.Pending,
+ step = TaskStep.CleanAndSync,
+ stepState = StepState.Queued,
+ errors = emptyList(),
+ createdAt = Instant.now(),
+ modifiedAt = Instant.now()
+ )
+ ),
+ TaskClientStateDto(
+ taskId = "3",
+ businessPartnerResult = null,
+ processingState = TaskProcessingStateDto(
+ resultState = ResultState.Pending,
+ step = TaskStep.CleanAndSync,
+ stepState = StepState.Queued,
+ errors = emptyList(),
+ createdAt = Instant.now(),
+ modifiedAt = Instant.now()
+ )
+ )
+ )
+ )
+
+ // Orchestrator request new cleaning endpoint
+ gateWireMockServer.stubFor(
+ WireMock.post(WireMock.urlPathEqualTo(ORCHESTRATOR_REQUEST_NEW_CLEANING))
+ .willReturn(
+ WireMock.okJson(objectMapper.writeValueAsString(responseOrchestratorTaskResponse))
+ )
+ )
+ }
+
+ fun readSharingStates(businessPartnerType: BusinessPartnerType?, externalIds: Collection?): Collection {
+
+ return gateClient.sharingState.getSharingStates(PaginationRequest(), businessPartnerType, externalIds).content
+ }
+
}