From b94986e0f463d72bd178da5871bf84f0b46039ff Mon Sep 17 00:00:00 2001 From: Nico Koprowski Date: Thu, 20 Feb 2025 10:37:25 +0800 Subject: [PATCH] fix(Pool): not checking the LSA parent hierarchy when consuming golden record tasks --- CHANGELOG.md | 1 + .../bpdm/pool/service/TaskStepBuildService.kt | 42 ++++++++++++- .../pool/service/TaskResolutionServiceTest.kt | 62 +++++++++++++++++++ 3 files changed, 104 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 507762d6f..1a31dbe95 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -29,6 +29,7 @@ For changes to the BPDM Helm charts please consult the [changelog](charts/bpdm/C - BPDM Pool: Fix resolved tasks by providing business partner data based on the database state. Returned result is now consistent. ([#1158](https://github.com/eclipse-tractusx/bpdm/issues/1158)) - BPDM Pool: Fix missing legal entity (BPNL) associated to address in response while performing entity search ([#1191](https://github.com/eclipse-tractusx/bpdm/issues/1191)) - BPDM Pool: Fix not returning the most-up-to-date legal and site main address when it has been modified by an update to the site ([#1209](https://github.com/eclipse-tractusx/bpdm/issues/1209)) +- BPDM Pool: Add check for correct LSA parent hierarchy when consuming golden record tasks ([#1230](https://github.com/eclipse-tractusx/bpdm/issues/1230)) ## [6.2.0] - 2024-11-28 diff --git a/bpdm-pool/src/main/kotlin/org/eclipse/tractusx/bpdm/pool/service/TaskStepBuildService.kt b/bpdm-pool/src/main/kotlin/org/eclipse/tractusx/bpdm/pool/service/TaskStepBuildService.kt index 7b9df93a6..ce8efae79 100644 --- a/bpdm-pool/src/main/kotlin/org/eclipse/tractusx/bpdm/pool/service/TaskStepBuildService.kt +++ b/bpdm-pool/src/main/kotlin/org/eclipse/tractusx/bpdm/pool/service/TaskStepBuildService.kt @@ -29,6 +29,8 @@ import org.eclipse.tractusx.bpdm.pool.api.model.request.* import org.eclipse.tractusx.bpdm.pool.entity.LogisticAddressDb import org.eclipse.tractusx.bpdm.pool.exception.BpdmValidationException import org.eclipse.tractusx.bpdm.pool.repository.BpnRequestIdentifierRepository +import org.eclipse.tractusx.bpdm.pool.repository.LogisticAddressRepository +import org.eclipse.tractusx.bpdm.pool.repository.SiteRepository import org.eclipse.tractusx.orchestrator.api.model.* import org.springframework.stereotype.Service import java.time.Instant @@ -48,7 +50,9 @@ class TaskStepBuildService( private val siteService: SiteService, private val addressService: AddressService, private val bpnRequestIdentifierRepository: BpnRequestIdentifierRepository, - private val taskResolutionMapper: TaskResolutionMapper + private val taskResolutionMapper: TaskResolutionMapper, + private val logisticAddressRepository: LogisticAddressRepository, + private val siteRepository: SiteRepository ) { enum class CleaningError(val message: String) { @@ -76,6 +80,9 @@ class TaskStepBuildService( LEGAL_ENTITY_CONFIDENCE_CRITERIA_MISSING("Legal Entity has no confidence criteria"), MAIN_ADDRESS_BPN_REFERENCE_MISSING("The BpnA Reference of the site main address is missing"), LEGAL_ADDRESS_BPN_REFERENCE_MISSING("The BpnA Reference of the legal address is missing"), + SITE_WRONG_LEGAL_ENTITY_REFERENCE("The legal entity is not the parent of the site"), + ADDITIONAL_ADDRESS_WRONG_SITE_REFERENCE("The site is not the parent of the additional address"), + ADDITIONAL_ADDRESS_WRONG_LEGAL_ENTITY_REFERENCE("The legal entity is not the parent of the additional address") } @Transactional @@ -83,6 +90,8 @@ class TaskStepBuildService( val taskEntryBpnMapping = TaskEntryBpnMapping(listOf(taskEntry), bpnRequestIdentifierRepository) val businessPartnerDto = taskEntry.businessPartner + assertParentsConsistent(businessPartnerDto, taskEntryBpnMapping) + val legalEntityResult = processLegalEntity(businessPartnerDto, taskEntryBpnMapping) val siteResult = processSite(businessPartnerDto, legalEntityResult.bpnReference.referenceValue!!, taskEntryBpnMapping) val addressResult = processAdditionalAddress(businessPartnerDto, legalEntityResult.bpnReference.referenceValue!!, siteResult?.bpnReference?.referenceValue, taskEntryBpnMapping) @@ -544,4 +553,35 @@ class TaskStepBuildService( throw BpdmValidationException("Country Code not recognized") } } + + private fun assertParentsConsistent(businessPartner: BusinessPartner, taskEntryBpnMapping: TaskEntryBpnMapping){ + val addressBpn = businessPartner.additionalAddress?.bpnReference?.let { taskEntryBpnMapping.getBpn(it) } + val siteBpn = businessPartner.site?.bpnReference?.let { taskEntryBpnMapping.getBpn(it) } + val legalEntityBpn = taskEntryBpnMapping.getBpn(businessPartner.legalEntity.bpnReference) + + if(siteBpn != null){ + val foundSite = siteRepository.findByBpn(siteBpn) + if(foundSite != null){ + if(foundSite.legalEntity.bpn != legalEntityBpn){ + throw BpdmValidationException(CleaningError.SITE_WRONG_LEGAL_ENTITY_REFERENCE.message) + } + } + } + + if(addressBpn != null){ + val foundAddress = logisticAddressRepository.findByBpn(addressBpn) + if(foundAddress != null){ + if(foundAddress.legalEntity!!.bpn != legalEntityBpn){ + throw BpdmValidationException(CleaningError.ADDITIONAL_ADDRESS_WRONG_LEGAL_ENTITY_REFERENCE.message) + } + if(foundAddress.site != null){ + if(foundAddress.site!!.bpn != siteBpn){ + throw BpdmValidationException(CleaningError.ADDITIONAL_ADDRESS_WRONG_SITE_REFERENCE.message) + } + } + } + } + + + } } \ No newline at end of file diff --git a/bpdm-pool/src/test/kotlin/org/eclipse/tractusx/bpdm/pool/service/TaskResolutionServiceTest.kt b/bpdm-pool/src/test/kotlin/org/eclipse/tractusx/bpdm/pool/service/TaskResolutionServiceTest.kt index f5e9e250f..f0baa3362 100644 --- a/bpdm-pool/src/test/kotlin/org/eclipse/tractusx/bpdm/pool/service/TaskResolutionServiceTest.kt +++ b/bpdm-pool/src/test/kotlin/org/eclipse/tractusx/bpdm/pool/service/TaskResolutionServiceTest.kt @@ -824,6 +824,68 @@ class TaskResolutionServiceTest @Autowired constructor( assertThat(updateResults.filter { it.errors.isNotEmpty() }).hasSize(0) } + @Test + fun `error on site update with wrong legal entity parent`() { + val siteCreateRequest = orchTestDataFactory.createSiteBusinessPartner("SITE_ON_LE1").copyWithBpnRequests() + upsertGoldenRecordIntoPool( + taskId = "TASK_1", + businessPartner = siteCreateRequest + ) + + val updateWithWrongLegalEntity = upsertGoldenRecordIntoPool( + taskId = "TASK_2", + businessPartner = orchTestDataFactory.createSiteBusinessPartner("SITE_ON_LE2").withSiteReferences( + siteCreateRequest.site!!.bpnReference, + siteCreateRequest.site!!.siteMainAddress!!.bpnReference + ) + ) + + assertThat(updateWithWrongLegalEntity[0].taskId).isEqualTo("TASK_2") + assertThat(updateWithWrongLegalEntity[0].errors).hasSize(1) + assertThat(updateWithWrongLegalEntity[0].errors[0].description).isEqualTo(CleaningError.SITE_WRONG_LEGAL_ENTITY_REFERENCE.message) + } + + @Test + fun `error on additional address update with wrong legal entity parent`() { + val addressCreateRequest = orchTestDataFactory.createFullBusinessPartner("ADDRESS_ON_LE1").copyWithBpnRequests() + upsertGoldenRecordIntoPool( + taskId = "TASK_1", + businessPartner = addressCreateRequest + ) + + val updateWithWrongLegalEntity = upsertGoldenRecordIntoPool( + taskId = "TASK_2", + businessPartner = orchTestDataFactory.createFullBusinessPartner("ADDRESS_ON_LE2").withAdditionalAddressReference( + addressCreateRequest.additionalAddress!!.bpnReference + ) + ) + + assertThat(updateWithWrongLegalEntity[0].taskId).isEqualTo("TASK_2") + assertThat(updateWithWrongLegalEntity[0].errors).hasSize(1) + assertThat(updateWithWrongLegalEntity[0].errors[0].description).isEqualTo(CleaningError.ADDITIONAL_ADDRESS_WRONG_LEGAL_ENTITY_REFERENCE.message) + } + + @Test + fun `error on additional address update with wrong site parent`() { + val addressCreateRequest = orchTestDataFactory.createFullBusinessPartner("ADDRESS_ON_SITE1").copyWithBpnRequests() + upsertGoldenRecordIntoPool( + taskId = "TASK_1", + businessPartner = addressCreateRequest + ) + + val updateWithWrongSite = upsertGoldenRecordIntoPool( + taskId = "TASK_2", + businessPartner = orchTestDataFactory.createFullBusinessPartner("ADDRESS_ON_SITE2") + .withLegalReferences(addressCreateRequest.legalEntity.bpnReference, addressCreateRequest.legalEntity.legalAddress.bpnReference) + .withAdditionalAddressReference(addressCreateRequest.additionalAddress!!.bpnReference) + ) + + assertThat(updateWithWrongSite[0].taskId).isEqualTo("TASK_2") + assertThat(updateWithWrongSite[0].errors).hasSize(1) + assertThat(updateWithWrongSite[0].errors[0].description).isEqualTo(CleaningError.ADDITIONAL_ADDRESS_WRONG_SITE_REFERENCE.message) + } + + fun upsertGoldenRecordIntoPool(taskId: String, businessPartner: BusinessPartner): List { val taskStep = singleTaskStep(taskId = taskId, businessPartner = businessPartner)