diff --git a/bpdm-gate/src/main/kotlin/org/eclipse/tractusx/bpdm/gate/Application.kt b/bpdm-gate/src/main/kotlin/org/eclipse/tractusx/bpdm/gate/Application.kt index 87a976425..67f22a5ed 100644 --- a/bpdm-gate/src/main/kotlin/org/eclipse/tractusx/bpdm/gate/Application.kt +++ b/bpdm-gate/src/main/kotlin/org/eclipse/tractusx/bpdm/gate/Application.kt @@ -22,7 +22,9 @@ package org.eclipse.tractusx.bpdm.gate import org.springframework.boot.autoconfigure.SpringBootApplication import org.springframework.boot.context.properties.ConfigurationPropertiesScan import org.springframework.boot.runApplication +import org.springframework.scheduling.annotation.EnableScheduling +@EnableScheduling @SpringBootApplication @ConfigurationPropertiesScan class Application diff --git a/bpdm-gate/src/main/kotlin/org/eclipse/tractusx/bpdm/gate/repository/SharingStateRepository.kt b/bpdm-gate/src/main/kotlin/org/eclipse/tractusx/bpdm/gate/repository/SharingStateRepository.kt index cb178ee61..8f4eb47df 100644 --- a/bpdm-gate/src/main/kotlin/org/eclipse/tractusx/bpdm/gate/repository/SharingStateRepository.kt +++ b/bpdm-gate/src/main/kotlin/org/eclipse/tractusx/bpdm/gate/repository/SharingStateRepository.kt @@ -20,6 +20,7 @@ package org.eclipse.tractusx.bpdm.gate.repository import org.eclipse.tractusx.bpdm.common.dto.BusinessPartnerType +import org.eclipse.tractusx.bpdm.gate.api.model.SharingStateType import org.eclipse.tractusx.bpdm.gate.entity.SharingState import org.springframework.data.jpa.domain.Specification import org.springframework.data.jpa.repository.JpaSpecificationExecutor @@ -52,4 +53,6 @@ interface SharingStateRepository : PagingAndSortingRepository + } \ No newline at end of file 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 bce20444f..f31b68694 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 @@ -25,7 +25,9 @@ import org.eclipse.tractusx.bpdm.common.model.StageType import org.eclipse.tractusx.bpdm.common.service.toPageDto import org.eclipse.tractusx.bpdm.common.util.copyAndSync import org.eclipse.tractusx.bpdm.common.util.replace +import org.eclipse.tractusx.bpdm.gate.api.exception.BusinessPartnerSharingError import org.eclipse.tractusx.bpdm.gate.api.model.ChangelogType +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.request.BusinessPartnerOutputRequest import org.eclipse.tractusx.bpdm.gate.api.model.response.BusinessPartnerInputDto @@ -35,11 +37,13 @@ import org.eclipse.tractusx.bpdm.gate.entity.ChangelogEntry 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.SharingStateRepository 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.scheduling.annotation.Scheduled import org.springframework.stereotype.Service import org.springframework.transaction.annotation.Transactional @@ -50,7 +54,8 @@ class BusinessPartnerService( private val sharingStateService: SharingStateService, private val changelogRepository: ChangelogRepository, private val orchestrationApiClient: OrchestrationApiClient, - private val orchestratorMappings: OrchestratorMappings + private val orchestratorMappings: OrchestratorMappings, + private val sharingStateRepository: SharingStateRepository ) { @Transactional @@ -91,7 +96,7 @@ class BusinessPartnerService( val taskCreateResponse = createGoldenRecordTasks(orchestratorBusinessPartnersDto) for (i in partners.indices) { - updateSharingState(partners[i], taskCreateResponse.createdTasks[i]) + updateSharingState(partners[i].externalId, taskCreateResponse.createdTasks[i]) } return businessPartnerRepository.saveAll(partners) @@ -230,16 +235,59 @@ class BusinessPartnerService( ) } - private fun updateSharingState(entity: BusinessPartner, stateDto: TaskClientStateDto) { + private fun updateSharingState(externalId: String, stateDto: TaskClientStateDto) { + + val errorMessage = if (stateDto.processingState.errors.isNotEmpty()) stateDto.processingState.errors.joinToString(" // ") { it.description } else null + val errorCode = if (stateDto.processingState.errors.isNotEmpty()) BusinessPartnerSharingError.SharingProcessError else null + sharingStateService.upsertSharingState( SharingStateDto( BusinessPartnerType.ADDRESS, - entity.externalId, + externalId, sharingStateType = orchestratorMappings.toSharingStateType(stateDto.processingState.resultState), + sharingErrorCode = errorCode, + sharingErrorMessage = errorMessage, taskId = stateDto.taskId ) ) + } + + @Scheduled(cron = "\${cleaningService.pollingCron:-}", zone = "UTC") + fun finishCleaningTask() { + + var validBusinessPartner: List = emptyList() + + val sharingStates = sharingStateRepository.findBySharingStateType(SharingStateType.Pending) + val nonNullTaskIds = sharingStates.mapNotNull { it.taskId } + + val taskStates = orchestrationApiClient.goldenRecordTasks.searchTaskStates(TaskStateRequest(nonNullTaskIds)) + val sharingStateMap = sharingStates.associateBy { it.taskId } + + //Task verification and map + taskStates.tasks.forEach { task -> + + val relatedSharingState = sharingStateMap[task.taskId] + + // Check if relatedSharingState exists + if (relatedSharingState != null) { + if (task.processingState.resultState == ResultState.Success) { + val businessPartner = orchestratorMappings.toBusinessPartner(task.businessPartnerResult!!, relatedSharingState.externalId) + validBusinessPartner = validBusinessPartner.plus(businessPartner) + + // Set Sharing State to Success + updateSharingState(businessPartner.externalId, task) + } else if (task.processingState.resultState == ResultState.Error) { + // Set related Sharing State Type as Error + updateSharingState(relatedSharingState.externalId, task) + } + } + } + + //If it is cleaned, upsert Output + if (validBusinessPartner.isNotEmpty()) { + upsertBusinessPartnersOutput(validBusinessPartner) + } } } 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 index 5f352d67e..485336479 100644 --- 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 @@ -24,6 +24,7 @@ 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.common.model.StageType 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 @@ -127,4 +128,82 @@ class OrchestratorMappings( ResultState.Success -> SharingStateType.Success ResultState.Error -> SharingStateType.Error } + + //Mapping BusinessPartnerGenericDto from to BusinessPartner + fun toBusinessPartner(entity: BusinessPartnerGenericDto, externalId: String) = BusinessPartner( + externalId = externalId, + nameParts = entity.nameParts.toMutableList(), + shortName = entity.shortName, + identifiers = entity.identifiers.map { toIdentifier(it) }.toSortedSet(), + legalForm = entity.legalForm, + states = entity.states.map { toState(it) }.toSortedSet(), + classifications = entity.classifications.map { toClassification(it) }.toSortedSet(), + roles = entity.roles.toSortedSet(), + postalAddress = toPostalAddress(entity.postalAddress), + bpnL = entity.bpnL, + bpnS = entity.bpnS, + bpnA = entity.bpnA, + stage = StageType.Output + ) + + private fun toIdentifier(dto: BusinessPartnerIdentifierDto) = + Identifier(type = dto.type, value = dto.value, issuingBody = dto.issuingBody) + + private fun toState(dto: BusinessPartnerStateDto) = + State(type = dto.type, validFrom = dto.validFrom, validTo = dto.validTo, description = dto.description) + + private fun toClassification(dto: ClassificationDto) = + Classification(type = dto.type, code = dto.code, value = dto.value) + + private fun toPostalAddress(entity: PostalAddressDto) = + PostalAddress( + addressType = entity.addressType, + physicalPostalAddress = entity.physicalPostalAddress?.let(::toPhysicalPostalAddress), + alternativePostalAddress = entity.alternativePostalAddress?.let(this::toAlternativePostalAddress) + ) + + private fun toPhysicalPostalAddress(dto: PhysicalPostalAddressDto) = + PhysicalPostalAddress( + geographicCoordinates = dto.geographicCoordinates?.let(::toGeographicCoordinate), + country = dto.country, + administrativeAreaLevel1 = dto.administrativeAreaLevel1, + administrativeAreaLevel2 = dto.administrativeAreaLevel2, + administrativeAreaLevel3 = dto.administrativeAreaLevel3, + postalCode = dto.postalCode, + city = dto.city, + district = dto.district, + street = dto.street?.let(::toStreet), + companyPostalCode = dto.companyPostalCode, + industrialZone = dto.industrialZone, + building = dto.building, + floor = dto.floor, + door = dto.door + ) + + private fun toAlternativePostalAddress(dto: AlternativePostalAddressDto) = + AlternativePostalAddress( + geographicCoordinates = dto.geographicCoordinates?.let(::toGeographicCoordinate), + country = dto.country, + administrativeAreaLevel1 = dto.administrativeAreaLevel1, + postalCode = dto.postalCode, + city = dto.city, + deliveryServiceType = dto.deliveryServiceType, + deliveryServiceQualifier = dto.deliveryServiceQualifier, + deliveryServiceNumber = dto.deliveryServiceNumber + ) + + private fun toStreet(dto: StreetDto) = + Street( + name = dto.name, + houseNumber = dto.houseNumber, + milestone = dto.milestone, + direction = dto.direction, + namePrefix = dto.namePrefix, + additionalNamePrefix = dto.additionalNamePrefix, + nameSuffix = dto.nameSuffix, + additionalNameSuffix = dto.additionalNameSuffix + ) + + private fun toGeographicCoordinate(dto: GeoCoordinateDto) = + GeographicCoordinate(latitude = dto.latitude, longitude = dto.longitude, altitude = dto.altitude) } \ No newline at end of file diff --git a/bpdm-gate/src/main/resources/application.properties b/bpdm-gate/src/main/resources/application.properties index e1e65a3ce..b81a1580a 100644 --- a/bpdm-gate/src/main/resources/application.properties +++ b/bpdm-gate/src/main/resources/application.properties @@ -62,6 +62,8 @@ spring.jpa.properties.hibernate.order_inserts=true #Flyway configuration spring.flyway.enabled=true spring.flyway.schemas=bpdmgate +#Cleaning Task Job Configurations +goldenRecordTask.pollingCron=- 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 25fb70e51..b0b3d173e 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 @@ -29,15 +29,18 @@ 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.common.exception.BpdmNullMappingException import org.eclipse.tractusx.bpdm.gate.api.client.GateClient +import org.eclipse.tractusx.bpdm.gate.api.exception.BusinessPartnerSharingError 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.request.BusinessPartnerOutputRequest import org.eclipse.tractusx.bpdm.gate.api.model.response.BusinessPartnerInputDto +import org.eclipse.tractusx.bpdm.gate.api.model.response.BusinessPartnerOutputDto 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.bpdm.gate.entity.generic.BusinessPartner +import org.eclipse.tractusx.bpdm.gate.service.BusinessPartnerService +import org.eclipse.tractusx.bpdm.gate.util.* import org.eclipse.tractusx.orchestrator.api.model.* import org.junit.jupiter.api.Assertions.assertEquals import org.junit.jupiter.api.BeforeEach @@ -62,10 +65,12 @@ import java.time.Instant class BusinessPartnerControllerIT @Autowired constructor( val testHelpers: DbTestHelpers, val gateClient: GateClient, - val objectMapper: ObjectMapper + val objectMapper: ObjectMapper, + val businessPartnerService: BusinessPartnerService ) { companion object { const val ORCHESTRATOR_CREATE_TASKS_URL = "/api/golden-record-tasks" + const val ORCHESTRATOR_SEARCH_TASK_STATES_URL = "/api/golden-record-tasks/state/search" @JvmField @RegisterExtension @@ -85,6 +90,7 @@ class BusinessPartnerControllerIT @Autowired constructor( testHelpers.truncateDbTables() gateWireMockServer.resetAll() this.mockOrchestratorApi() + this.mockOrchestratorApiCleaned() } @Test @@ -286,6 +292,13 @@ class BusinessPartnerControllerIT @Autowired constructor( .isEqualTo(requests.map(::toExpectedResponse)) } + private fun assertUpsertOutputResponsesMatchRequests(responses: Collection, requests: List) { + Assertions.assertThat(responses) + .usingRecursiveComparison() + .ignoringFieldsOfTypes(Instant::class.java) + .isEqualTo(requests.map(::toExpectedResponseOutput)) + } + private fun toExpectedResponse(request: BusinessPartnerInputRequest): BusinessPartnerInputDto { // same sorting order as defined for entity return BusinessPartnerInputDto( @@ -307,6 +320,37 @@ class BusinessPartnerControllerIT @Autowired constructor( ) } + private fun toExpectedResponseOutput(request: BusinessPartnerOutputRequest): BusinessPartnerOutputDto { + // same sorting order as defined for entity + return BusinessPartnerOutputDto( + externalId = request.externalId, + nameParts = request.nameParts, + shortName = request.shortName, + identifiers = request.identifiers.toSortedSet(identifierDtoComparator), + legalForm = request.legalForm, + states = request.states.toSortedSet(stateDtoComparator), + classifications = request.classifications.toSortedSet(classificationDtoComparator), + roles = request.roles.toSortedSet(), + postalAddress = request.postalAddress, + isOwnCompanyData = request.isOwnCompanyData, + bpnL = request.bpnL ?: throw BpdmNullMappingException( + BusinessPartner::class, + BusinessPartnerOutputDto::class, + BusinessPartner::bpnL, + request.externalId + ), + bpnS = request.bpnS, + bpnA = request.bpnA ?: throw BpdmNullMappingException( + BusinessPartner::class, + BusinessPartnerOutputDto::class, + BusinessPartner::bpnA, + request.externalId + ), + createdAt = Instant.now(), + updatedAt = Instant.now() + ) + } + val identifierDtoComparator = compareBy( BusinessPartnerIdentifierDto::type, BusinessPartnerIdentifierDto::value, @@ -390,9 +434,134 @@ class BusinessPartnerControllerIT @Autowired constructor( ) } + private fun mockOrchestratorApiCleaned() { + val TaskStateResponse = + TaskStateResponse( + listOf( + TaskClientStateDto( + taskId = "0", + businessPartnerResult = BusinessPartnerGenericMockValues.businessPartner1, + processingState = TaskProcessingStateDto( + resultState = ResultState.Success, + step = TaskStep.CleanAndSync, + stepState = StepState.Queued, + errors = emptyList(), + createdAt = Instant.now(), + modifiedAt = Instant.now(), + timeout = Instant.now() + ) + ), + TaskClientStateDto( + taskId = "1", + businessPartnerResult = null, + processingState = TaskProcessingStateDto( + resultState = ResultState.Error, + step = TaskStep.CleanAndSync, + stepState = StepState.Queued, + errors = listOf( + TaskErrorDto(TaskErrorType.Timeout, "Major Error"), + TaskErrorDto(TaskErrorType.Unspecified, "Minor Error") + ), + createdAt = Instant.now(), + modifiedAt = Instant.now(), + timeout = Instant.now() + ) + ) + ) + ) + + gateWireMockServer.stubFor( + WireMock.post(WireMock.urlPathEqualTo(ORCHESTRATOR_SEARCH_TASK_STATES_URL)) + .willReturn( + WireMock.okJson(objectMapper.writeValueAsString(TaskStateResponse)) + ) + ) + } + fun readSharingStates(businessPartnerType: BusinessPartnerType?, externalIds: Collection?): Collection { return gateClient.sharingState.getSharingStates(PaginationRequest(), businessPartnerType, externalIds).content } + @Test + fun `insert one business partners and finalize cleaning task without error`() { + + val outputBusinessPartners = listOf( + BusinessPartnerNonVerboseValues.bpOutputRequestCleaned + ) + + val upsertRequests = listOf( + BusinessPartnerNonVerboseValues.bpInputRequestCleaned, + BusinessPartnerNonVerboseValues.bpInputRequestError + ) + gateClient.businessParters.upsertBusinessPartnersInput(upsertRequests).body!! + + val externalId4 = BusinessPartnerNonVerboseValues.bpInputRequestCleaned.externalId + val externalId5 = BusinessPartnerNonVerboseValues.bpInputRequestError.externalId + + val createdSharingState = listOf( + SharingStateDto( + businessPartnerType = BusinessPartnerType.ADDRESS, + externalId = externalId4, + sharingStateType = SharingStateType.Pending, + sharingErrorCode = null, + sharingErrorMessage = null, + bpn = null, + sharingProcessStarted = null, + taskId = "0" + ), + SharingStateDto( + businessPartnerType = BusinessPartnerType.ADDRESS, + externalId = externalId5, + sharingStateType = SharingStateType.Pending, + sharingErrorCode = null, + sharingErrorMessage = null, + bpn = null, + sharingProcessStarted = null, + taskId = "1" + ) + ) + + //Firstly verifies if the Sharing States was created for new Business Partners + val externalIds = listOf(externalId4, externalId5) + val upsertSharingStateResponses = readSharingStates(BusinessPartnerType.ADDRESS, externalIds) + testHelpers.assertRecursively(upsertSharingStateResponses).isEqualTo(createdSharingState) + + // Call Finish Cleaning Method + businessPartnerService.finishCleaningTask() + + val cleanedSharingState = listOf( + SharingStateDto( + businessPartnerType = BusinessPartnerType.ADDRESS, + externalId = externalId4, + sharingStateType = SharingStateType.Success, + sharingErrorCode = null, + sharingErrorMessage = null, + bpn = null, + sharingProcessStarted = null, + taskId = "0" + ), + SharingStateDto( + businessPartnerType = BusinessPartnerType.ADDRESS, + externalId = externalId5, + sharingStateType = SharingStateType.Error, + sharingErrorCode = BusinessPartnerSharingError.SharingProcessError, + sharingErrorMessage = "Major Error // Minor Error", + bpn = null, + sharingProcessStarted = null, + taskId = "1" + ) + ) + + //Check for both Sharing State changes (Error and Success) + val readCleanedSharingState = readSharingStates(BusinessPartnerType.ADDRESS, externalIds) + testHelpers.assertRecursively(readCleanedSharingState).isEqualTo(cleanedSharingState) + + //Assert that Cleaned Golden Record is persisted in the Output correctly + val searchResponsePage = gateClient.businessParters.getBusinessPartnersOutput(listOf(externalId4)) + assertUpsertOutputResponsesMatchRequests(searchResponsePage.content, outputBusinessPartners) + + } + + } diff --git a/bpdm-gate/src/test/kotlin/org/eclipse/tractusx/bpdm/gate/util/BusinessPartnerGenericValues.kt b/bpdm-gate/src/test/kotlin/org/eclipse/tractusx/bpdm/gate/util/BusinessPartnerGenericValues.kt new file mode 100644 index 000000000..1ca277cf4 --- /dev/null +++ b/bpdm-gate/src/test/kotlin/org/eclipse/tractusx/bpdm/gate/util/BusinessPartnerGenericValues.kt @@ -0,0 +1,127 @@ +/******************************************************************************* + * 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.util + +import com.neovisionaries.i18n.CountryCode +import org.eclipse.tractusx.bpdm.common.dto.* +import org.eclipse.tractusx.bpdm.common.model.BusinessStateType +import org.eclipse.tractusx.bpdm.common.model.ClassificationType +import org.eclipse.tractusx.bpdm.common.model.DeliveryServiceType +import org.eclipse.tractusx.orchestrator.api.model.* +import org.eclipse.tractusx.orchestrator.api.model.AlternativePostalAddressDto +import org.eclipse.tractusx.orchestrator.api.model.PhysicalPostalAddressDto +import org.eclipse.tractusx.orchestrator.api.model.StreetDto +import java.time.LocalDateTime + +object BusinessPartnerGenericMockValues { + + //Business Partner with two entries in every collection + val businessPartner1 = BusinessPartnerGenericDto( + nameParts = listOf("part-cleaned-1", "name-cleaned-2"), + shortName = "shot-name-cleaned", + identifiers = listOf( + BusinessPartnerIdentifierDto( + type = "identifier-type-1-cleaned", + value = "identifier-value-1-cleaned", + issuingBody = "issuingBody-1-cleaned" + ), + BusinessPartnerIdentifierDto( + type = "identifier-type-2-cleaned", + value = "identifier-value-2-cleaned", + issuingBody = "issuingBody-2-cleaned" + ), + ), + legalForm = "legal-form-cleaned", + states = listOf( + BusinessPartnerStateDto( + validFrom = LocalDateTime.of(2020, 9, 22, 15, 50), + validTo = LocalDateTime.of(2023, 10, 23, 16, 40), + type = BusinessStateType.INACTIVE, + description = "business-state-description-1" + ), + BusinessPartnerStateDto( + validFrom = LocalDateTime.of(2000, 8, 21, 14, 30), + validTo = LocalDateTime.of(2020, 9, 22, 15, 50), + type = BusinessStateType.ACTIVE, + description = "business-state-description-2" + ) + ), + classifications = listOf( + ClassificationDto( + type = ClassificationType.NACE, + code = "code-1-cleaned", + value = "value-1-cleaned" + ), + ClassificationDto( + type = ClassificationType.NAF, + code = "code-2-cleaned", + value = "value-2-cleaned" + ), + ), + roles = listOf( + BusinessPartnerRole.CUSTOMER, + BusinessPartnerRole.SUPPLIER + ), + postalAddress = PostalAddressDto( + addressType = AddressType.AdditionalAddress, + physicalPostalAddress = PhysicalPostalAddressDto( + geographicCoordinates = GeoCoordinateDto(0.5f, 0.5f, 0.5f), + country = CountryCode.PT, + administrativeAreaLevel1 = "PT-PT", + administrativeAreaLevel2 = "pt-admin-level-2-cleaned", + administrativeAreaLevel3 = "pt-admin-level-3-cleaned", + postalCode = "phys-postal-code-cleaned", + city = "city", + district = "district", + street = StreetDto( + name = "name", + houseNumber = "house-number", + milestone = "milestone", + direction = "direction", + namePrefix = "name-prefix", + additionalNamePrefix = "add-name-prefix", + nameSuffix = "name-suffix", + additionalNameSuffix = "add-name-suffix" + + ), + companyPostalCode = "comp-postal-code", + industrialZone = "industrial-zone", + building = "building", + floor = "floor", + door = "door" + ), + alternativePostalAddress = AlternativePostalAddressDto( + geographicCoordinates = GeoCoordinateDto(0.6f, 0.6f, 0.6f), + country = CountryCode.PT, + administrativeAreaLevel1 = "PT-PT", + postalCode = "postal-code-cleaned", + city = "alt-city-cleaned", + deliveryServiceNumber = "delivery-service-number-cleaned", + deliveryServiceQualifier = "delivery-service-qualifier-cleaned", + deliveryServiceType = DeliveryServiceType.PO_BOX + ) + ), + ownerBpnL = "BPNL_CLEANED_VALUES", + bpnL = "000000123AAA123", + bpnS = "000000123BBB222", + bpnA = "000000123CCC333" + ) + +} \ No newline at end of file diff --git a/bpdm-gate/src/test/kotlin/org/eclipse/tractusx/bpdm/gate/util/BusinessPartnerNonVerboseValues.kt b/bpdm-gate/src/test/kotlin/org/eclipse/tractusx/bpdm/gate/util/BusinessPartnerNonVerboseValues.kt index 4719482eb..e6da6482d 100644 --- a/bpdm-gate/src/test/kotlin/org/eclipse/tractusx/bpdm/gate/util/BusinessPartnerNonVerboseValues.kt +++ b/bpdm-gate/src/test/kotlin/org/eclipse/tractusx/bpdm/gate/util/BusinessPartnerNonVerboseValues.kt @@ -19,7 +19,7 @@ package org.eclipse.tractusx.bpdm.gate.util -import org.eclipse.tractusx.bpdm.common.dto.* +import org.eclipse.tractusx.bpdm.common.dto.AddressIdentifierDto import org.eclipse.tractusx.bpdm.gate.api.model.AddressGateOutputChildRequest import org.eclipse.tractusx.bpdm.gate.api.model.BusinessPartnerPostalAddressDto import org.eclipse.tractusx.bpdm.gate.api.model.request.* @@ -43,6 +43,13 @@ object BusinessPartnerNonVerboseValues { val bpInputRequestChina = BusinessPartnerVerboseValues.bpInputRequestChina + val bpInputRequestCleaned = BusinessPartnerVerboseValues.bpInputRequestCleaned + + val bpInputRequestError = BusinessPartnerVerboseValues.bpInputRequestError + + //Output Business Partner Test Values + val bpOutputRequestCleaned = BusinessPartnerVerboseValues.bpOutputRequestCleaned + val legalEntityGateInputRequest1 = LegalEntityGateInputRequest( legalEntity = BusinessPartnerVerboseValues.legalEntity1, legalAddress = BusinessPartnerVerboseValues.physicalAddress1, diff --git a/bpdm-gate/src/test/kotlin/org/eclipse/tractusx/bpdm/gate/util/BusinessPartnerVerboseValues.kt b/bpdm-gate/src/test/kotlin/org/eclipse/tractusx/bpdm/gate/util/BusinessPartnerVerboseValues.kt index 603680ff9..81ff49943 100644 --- a/bpdm-gate/src/test/kotlin/org/eclipse/tractusx/bpdm/gate/util/BusinessPartnerVerboseValues.kt +++ b/bpdm-gate/src/test/kotlin/org/eclipse/tractusx/bpdm/gate/util/BusinessPartnerVerboseValues.kt @@ -29,6 +29,7 @@ import org.eclipse.tractusx.bpdm.common.model.DeliveryServiceType import org.eclipse.tractusx.bpdm.common.service.toDto import org.eclipse.tractusx.bpdm.gate.api.model.* import org.eclipse.tractusx.bpdm.gate.api.model.request.BusinessPartnerInputRequest +import org.eclipse.tractusx.bpdm.gate.api.model.request.BusinessPartnerOutputRequest import org.eclipse.tractusx.bpdm.gate.api.model.response.* import java.time.Instant import java.time.LocalDateTime @@ -747,4 +748,135 @@ object BusinessPartnerVerboseValues { bpnA = "BPNA0000000001XY" ) + val bpInputRequestCleaned = BusinessPartnerInputRequest( + externalId = externalId4, + nameParts = listOf("Name Part Value"), + shortName = "Random Short Name", + legalForm = "Random Form Value", + isOwnCompanyData = true, + identifiers = listOf( + bpIdentifier1, bpIdentifier2, bpIdentifier1 + ), + classifications = listOf( + bpClassification1, bpClassification3 + ), + states = listOf(bpState2, bpState1), + roles = listOf(BusinessPartnerRole.CUSTOMER, BusinessPartnerRole.SUPPLIER), + postalAddress = bpPostalAddressInputDtoFull, + bpnL = "BPNL0000000002XY", + bpnS = "BPNS0000000003X9", + bpnA = "BPNA0000000001XY" + ) + + val bpInputRequestError = BusinessPartnerInputRequest( + externalId = externalId5, + nameParts = listOf("Name Part Value"), + shortName = "Random Short Name", + legalForm = "Random Form Value", + isOwnCompanyData = true, + identifiers = listOf( + bpIdentifier1, bpIdentifier2, bpIdentifier1 + ), + classifications = listOf( + bpClassification1, bpClassification3 + ), + states = listOf(bpState2, bpState1), + roles = listOf(BusinessPartnerRole.CUSTOMER, BusinessPartnerRole.SUPPLIER), + postalAddress = bpPostalAddressInputDtoFull, + bpnL = "BPNL0000000002XY", + bpnS = "BPNS0000000003X9", + bpnA = "BPNA0000000001XY" + ) + + val bpOutputRequestCleaned = BusinessPartnerOutputRequest( + externalId = externalId4, + nameParts = listOf("part-cleaned-1", "name-cleaned-2"), + shortName = "shot-name-cleaned", + legalForm = "legal-form-cleaned", + identifiers = listOf( + BusinessPartnerIdentifierDto( + type = "identifier-type-1-cleaned", + value = "identifier-value-1-cleaned", + issuingBody = "issuingBody-1-cleaned" + ), + BusinessPartnerIdentifierDto( + type = "identifier-type-2-cleaned", + value = "identifier-value-2-cleaned", + issuingBody = "issuingBody-2-cleaned" + ), + ), + classifications = listOf( + ClassificationDto( + type = ClassificationType.NACE, + code = "code-1-cleaned", + value = "value-1-cleaned" + ), + ClassificationDto( + type = ClassificationType.NAF, + code = "code-2-cleaned", + value = "value-2-cleaned" + ), + ), + states = listOf( + BusinessPartnerStateDto( + validFrom = LocalDateTime.of(2020, 9, 22, 15, 50), + validTo = LocalDateTime.of(2023, 10, 23, 16, 40), + type = BusinessStateType.INACTIVE, + description = "business-state-description-1" + ), + BusinessPartnerStateDto( + validFrom = LocalDateTime.of(2000, 8, 21, 14, 30), + validTo = LocalDateTime.of(2020, 9, 22, 15, 50), + type = BusinessStateType.ACTIVE, + description = "business-state-description-2" + ) + ), + roles = listOf( + BusinessPartnerRole.CUSTOMER, + BusinessPartnerRole.SUPPLIER + ), + postalAddress = BusinessPartnerPostalAddressDto( + addressType = AddressType.AdditionalAddress, + physicalPostalAddress = PhysicalPostalAddressGateDto( + geographicCoordinates = GeoCoordinateDto(0.5f, 0.5f, 0.5f), + country = CountryCode.PT, + administrativeAreaLevel1 = "PT-PT", + administrativeAreaLevel2 = "pt-admin-level-2-cleaned", + administrativeAreaLevel3 = "pt-admin-level-3-cleaned", + postalCode = "phys-postal-code-cleaned", + city = "city", + district = "district", + street = StreetGateDto( + name = "name", + houseNumber = "house-number", + milestone = "milestone", + direction = "direction", + namePrefix = "name-prefix", + additionalNamePrefix = "add-name-prefix", + nameSuffix = "name-suffix", + additionalNameSuffix = "add-name-suffix" + + ), + companyPostalCode = "comp-postal-code", + industrialZone = "industrial-zone", + building = "building", + floor = "floor", + door = "door" + ), + alternativePostalAddress = AlternativePostalAddressGateDto( + geographicCoordinates = GeoCoordinateDto(0.6f, 0.6f, 0.6f), + country = CountryCode.PT, + administrativeAreaLevel1 = "PT-PT", + postalCode = "postal-code-cleaned", + city = "alt-city-cleaned", + deliveryServiceNumber = "delivery-service-number-cleaned", + deliveryServiceQualifier = "delivery-service-qualifier-cleaned", + deliveryServiceType = DeliveryServiceType.PO_BOX + ) + ), + bpnL = "000000123AAA123", + bpnS = "000000123BBB222", + bpnA = "000000123CCC333" + ) + } \ No newline at end of file diff --git a/bpdm-orchestrator/src/main/kotlin/org/eclipse/tractusx/bpdm/orchestrator/controller/GoldenRecordTaskController.kt b/bpdm-orchestrator/src/main/kotlin/org/eclipse/tractusx/bpdm/orchestrator/controller/GoldenRecordTaskController.kt index 855ceacb6..ff057e6e5 100644 --- a/bpdm-orchestrator/src/main/kotlin/org/eclipse/tractusx/bpdm/orchestrator/controller/GoldenRecordTaskController.kt +++ b/bpdm-orchestrator/src/main/kotlin/org/eclipse/tractusx/bpdm/orchestrator/controller/GoldenRecordTaskController.kt @@ -19,6 +19,7 @@ package org.eclipse.tractusx.bpdm.orchestrator.controller +import org.eclipse.tractusx.bpdm.common.dto.* import org.eclipse.tractusx.bpdm.common.exception.BpdmUpsertLimitException import org.eclipse.tractusx.bpdm.orchestrator.config.ApiConfigProperties import org.eclipse.tractusx.bpdm.orchestrator.service.GoldenRecordTaskService @@ -28,6 +29,7 @@ import org.springframework.http.HttpStatus import org.springframework.security.access.prepost.PreAuthorize import org.springframework.web.bind.annotation.ResponseStatus import org.springframework.web.bind.annotation.RestController +import java.util.* @RestController class GoldenRecordTaskController(