From 8a6e5195b9ad492695a11ef46dc6c5b707d12586 Mon Sep 17 00:00:00 2001 From: Martin Kaeser Date: Wed, 7 Jun 2023 16:49:52 +0200 Subject: [PATCH] feat(bridge-tests): Tests for syncing new legal entities, site & addresses #210 --- .../catenax/bpdm/bridge/dummy/BridgeSyncIT.kt | 237 +++++++++++++++++- .../bridge/dummy/testdata/CommonValues.kt | 9 + .../dummy/testdata/GateRequestValues.kt | 49 ++++ .../bpdm/bridge/dummy/util/TestHelpers.kt | 1 + 4 files changed, 286 insertions(+), 10 deletions(-) diff --git a/bpdm-bridge-dummy/src/test/kotlin/com/catenax/bpdm/bridge/dummy/BridgeSyncIT.kt b/bpdm-bridge-dummy/src/test/kotlin/com/catenax/bpdm/bridge/dummy/BridgeSyncIT.kt index c3298f620..627edc4dc 100644 --- a/bpdm-bridge-dummy/src/test/kotlin/com/catenax/bpdm/bridge/dummy/BridgeSyncIT.kt +++ b/bpdm-bridge-dummy/src/test/kotlin/com/catenax/bpdm/bridge/dummy/BridgeSyncIT.kt @@ -20,12 +20,20 @@ package com.catenax.bpdm.bridge.dummy import com.catenax.bpdm.bridge.dummy.client.BridgeClient -import com.catenax.bpdm.bridge.dummy.util.BpdmGateContextInitializer -import com.catenax.bpdm.bridge.dummy.util.BpdmPoolContextInitializer -import com.catenax.bpdm.bridge.dummy.util.OpenSearchContextInitializer -import com.catenax.bpdm.bridge.dummy.util.PostgreSQLContextInitializer +import com.catenax.bpdm.bridge.dummy.testdata.GateRequestValues +import com.catenax.bpdm.bridge.dummy.util.* +import org.assertj.core.api.Assertions.assertThat +import org.eclipse.tractusx.bpdm.common.dto.request.AddressPartnerBpnSearchRequest import org.eclipse.tractusx.bpdm.common.dto.request.PaginationRequest +import org.eclipse.tractusx.bpdm.common.dto.request.SiteBpnSearchRequest +import org.eclipse.tractusx.bpdm.common.dto.response.LogisticAddressVerboseDto import org.eclipse.tractusx.bpdm.gate.api.client.GateClient +import org.eclipse.tractusx.bpdm.gate.api.model.* +import org.eclipse.tractusx.bpdm.gate.api.model.request.AddressGateInputRequest +import org.eclipse.tractusx.bpdm.gate.api.model.request.ChangeLogSearchRequest +import org.eclipse.tractusx.bpdm.gate.api.model.request.LegalEntityGateInputRequest +import org.eclipse.tractusx.bpdm.gate.api.model.request.SiteGateInputRequest +import org.eclipse.tractusx.bpdm.gate.api.model.response.SharingStateDto import org.eclipse.tractusx.bpdm.pool.api.client.PoolApiClient import org.junit.jupiter.api.Test import com.catenax.bpdm.bridge.dummy.testdata.GateRequestValues @@ -46,6 +54,12 @@ import org.eclipse.tractusx.bpdm.pool.api.model.request.LegalEntityPropertiesSea import org.eclipse.tractusx.bpdm.pool.api.model.response.LegalEntityMatchVerboseDto import org.eclipse.tractusx.bpdm.pool.api.model.response.SitePoolVerboseDto import org.junit.jupiter.api.* +import org.eclipse.tractusx.bpdm.pool.api.model.request.AddressPropertiesSearchRequest +import org.eclipse.tractusx.bpdm.pool.api.model.request.ChangelogSearchRequest +import org.eclipse.tractusx.bpdm.pool.api.model.request.LegalEntityPropertiesSearchRequest +import org.eclipse.tractusx.bpdm.pool.api.model.response.LegalEntityMatchVerboseDto +import org.eclipse.tractusx.bpdm.pool.api.model.response.SitePoolVerboseDto +import org.junit.jupiter.api.* import org.springframework.beans.factory.annotation.Autowired import org.springframework.boot.test.context.SpringBootTest import org.springframework.test.context.ActiveProfiles @@ -61,17 +75,87 @@ private val DEFAULT_PAGINATION_REQUEST = PaginationRequest(0, 100) class BridgeSyncIT @Autowired constructor( val bridgeClient: BridgeClient, val gateClient: GateClient, - val poolClient: PoolApiClient + val poolClient: PoolApiClient, + val testHelpers: TestHelpers ) { + @BeforeEach + fun beforeEach() { + testHelpers.truncateDbTables() + testHelpers.createPoolMetadata() + } + + @Test + fun `just use API clients`() { + assertGateChangelogHasCount(0) + val poolChangelogResponses = poolClient.changelogs().getChangelogEntries( + paginationRequest = DEFAULT_PAGINATION_REQUEST, changelogSearchRequest = ChangelogSearchRequest(fromTime = null, bpns = null) + ) + assertThat(poolChangelogResponses.contentSize).isZero() + bridgeClient.bridge().triggerSync() + } + + @Test + fun `sync new legal entities`() { + val gateLegalEntityRequests = listOf( + GateRequestValues.legalEntityGateInputRequest1, + GateRequestValues.legalEntityGateInputRequest2, + GateRequestValues.legalEntityGateInputRequest3 + ) + gateClient.legalEntities().upsertLegalEntities(gateLegalEntityRequests) + + assertGateChangelogHasCount(3 + 3) // 3 LEs + 3 addresses + assertSharingStatesSuccessful(0) + + // Action: Sync from Gate to Pool and BPN back to Gate + bridgeClient.bridge().triggerSync() + + // 3 legal entities + 3 legal addresses + assertPoolChangelogHasCount(3 + 3) + + // 3 legal entities + val sharingStatesOkay = assertSharingStatesSuccessful(6) + val bpnByExternalId = buildBpnByExternalIdMap(sharingStatesOkay) + + val gateLegalEntityRequestByBpn = gateLegalEntityRequests.associateBy { bpnByExternalId[it.externalId]!! } + + val poolLegalEntityResponses = poolClient.legalEntities().getLegalEntities( + bpSearchRequest = LegalEntityPropertiesSearchRequest.EmptySearchRequest, + paginationRequest = DEFAULT_PAGINATION_REQUEST + ) + assertThat(poolLegalEntityResponses.contentSize).isEqualTo(3) + + val poolLegalEntityByBpn = poolLegalEntityResponses.content.associateBy { it.legalEntity.bpnl } + + val legalEntitiesGateAndPool = gateLegalEntityRequestByBpn.keys + .map { Pair(gateLegalEntityRequestByBpn[it]!!, poolLegalEntityByBpn[it]!!) } + + assertThat(legalEntitiesGateAndPool.size).isEqualTo(3) + legalEntitiesGateAndPool.forEach { (gateVersion, poolVersion) -> + assertEqualLegalEntity(gateVersion, poolVersion) + } + } + @Test - fun `use API clients`() { - val gateChangelogs = gateClient.changelog().getChangelogEntriesLsaType( - paginationRequest = PaginationRequest(0, 10), fromTime = null, lsaType = null + fun `sync new sites`() { + // site needs parent legal entity! + val gateLegalEntityRequests = listOf( + GateRequestValues.legalEntityGateInputRequest1, + GateRequestValues.legalEntityGateInputRequest2, + GateRequestValues.legalEntityGateInputRequest3 ) - val poolChangelogs = poolClient.businessPartners().getChangelogEntries( - paginationRequest = PaginationRequest(0, 10), modifiedAfter = null, bpn = null + gateClient.legalEntities().upsertLegalEntities(gateLegalEntityRequests) + + val gateSiteRequests = listOf( + GateRequestValues.siteGateInputRequest1, + GateRequestValues.siteGateInputRequest2 ) + gateClient.sites().upsertSites(gateSiteRequests) + + assertGateChangelogHasCount(3 + 2 + 3 + 2) // 3 LEs + 2 sites + 3 le addresses + 2 site main addresses + assertSharingStatesSuccessful(0) + + // Action: Sync from Gate to Pool and BPN back to Gate bridgeClient.bridge().triggerSync() val poolClient: PoolApiClient, val testHelpers: TestHelpers @@ -282,6 +366,139 @@ class BridgeSyncIT @Autowired constructor( assertThat(poolVersion.site.states.map { it.description }).isEqualTo(gateVersion.site.states.map { it.description }) } + private fun assertEqualAddress(gateVersion: AddressGateInputRequest, poolVersion: LogisticAddressVerboseDto) { + assertThat(poolVersion.name).isEqualTo(gateVersion.address.nameParts.first()) + assertThat(poolVersion.physicalPostalAddress.street?.name).isEqualTo(gateVersion.address.physicalPostalAddress.street?.name) + assertThat(poolVersion.physicalPostalAddress.baseAddress.city).isEqualTo(gateVersion.address.physicalPostalAddress.baseAddress.city) + assertThat(poolVersion.alternativePostalAddress?.deliveryServiceNumber).isEqualTo(gateVersion.address.alternativePostalAddress?.deliveryServiceNumber) + assertThat(poolVersion.alternativePostalAddress?.baseAddress?.city).isEqualTo(gateVersion.address.alternativePostalAddress?.baseAddress?.city) + + // 3 legal entities + 3 legal addresses & 2 sites + 2 main addresses + assertPoolChangelogHasCount(3 + 3 + 2 + 2) + + // 3 LEs + 2 sites + val sharingStatesOkay = assertSharingStatesSuccessful(3 + 2) + val bpnByExternalId = buildBpnByExternalIdMap(sharingStatesOkay) + + val gateSiteRequestsByBpn = gateSiteRequests.associateBy { bpnByExternalId[it.externalId]!! } + + val poolSiteResponses = poolClient.sites().searchSites( + siteSearchRequest = SiteBpnSearchRequest(sites = gateSiteRequestsByBpn.keys), + paginationRequest = DEFAULT_PAGINATION_REQUEST + ) + assertThat(poolSiteResponses.contentSize).isEqualTo(2) + + val poolSiteByBpn = poolSiteResponses.content.associateBy { it.site.bpns } + + val sitesGateAndPool = gateSiteRequestsByBpn.keys + .map { Pair(gateSiteRequestsByBpn[it]!!, poolSiteByBpn[it]!!) } + + assertThat(sitesGateAndPool.size).isEqualTo(2) + sitesGateAndPool.forEach { (gateVersion, poolVersion) -> + assertEqualSite(gateVersion, poolVersion) + } + } + + @Test + fun `sync new addresses`() { + // address needs parent legal entity and site! + val gateLegalEntityRequests = listOf( + GateRequestValues.legalEntityGateInputRequest1, + ) + gateClient.legalEntities().upsertLegalEntities(gateLegalEntityRequests) + val gateSiteRequests = listOf( + GateRequestValues.siteGateInputRequest1, + ) + gateClient.sites().upsertSites(gateSiteRequests) + + val gateAddressRequests = listOf( + GateRequestValues.addressGateInputRequest1, + GateRequestValues.addressGateInputRequest2 + ) + gateClient.addresses().upsertAddresses(gateAddressRequests) + + assertGateChangelogHasCount(1 + 1 + 2 + 2) // 1 LE + 1 site + 2 addresses + assertSharingStatesSuccessful(0) + + // Action: Sync from Gate to Pool and BPN back to Gate + bridgeClient.bridge().triggerSync() + + // 1 legal entity + 1 legal address & 1 site + 1 main address & 2 addresses + assertPoolChangelogHasCount(1 + 1 + 1 + 1 + 2) + + // 1 LE + 1 site + 2 addresses + val sharingStatesOkay = assertSharingStatesSuccessful(1 + 1 + 2) + val bpnByExternalId = buildBpnByExternalIdMap(sharingStatesOkay) + + val gateAddressRequestsByBpn = gateAddressRequests.associateBy { bpnByExternalId[it.externalId]!! } + + val poolAddressResponses = poolClient.addresses().searchAddresses( + addressSearchRequest = AddressPartnerBpnSearchRequest(addresses = gateAddressRequestsByBpn.keys), + paginationRequest = DEFAULT_PAGINATION_REQUEST + ) + assertThat(poolAddressResponses.contentSize).isEqualTo(2) + + val poolAddressByBpn = poolAddressResponses.content.associateBy { it.bpna } + + val addressesGateAndPool = gateAddressRequestsByBpn.keys + .map { Pair(gateAddressRequestsByBpn[it]!!, poolAddressByBpn[it]!!) } + + assertThat(addressesGateAndPool.size).isEqualTo(2) + addressesGateAndPool.forEach { (gateVersion, poolVersion) -> + assertEqualAddress(gateVersion, poolVersion) + } + } + + private fun buildBpnByExternalIdMap(sharingStatesOkay: List) = + sharingStatesOkay + .associateBy { it.externalId } + .mapValues { it.value.bpn } + + private fun assertGateChangelogHasCount(changelogCount: Int) { + val gateChangelogResponses = gateClient.changelog().getInputChangelog( + paginationRequest = DEFAULT_PAGINATION_REQUEST, + searchRequest = ChangeLogSearchRequest(fromTime = null, lsaTypes = emptySet()) + ) + assertThat(gateChangelogResponses.contentSize).isEqualTo(changelogCount) + } + + private fun assertPoolChangelogHasCount(changelogCount: Int) { + val poolChangelogResponses = poolClient.changelogs().getChangelogEntries( + paginationRequest = DEFAULT_PAGINATION_REQUEST, + changelogSearchRequest = ChangelogSearchRequest(fromTime = null, bpns = null) + + ) + assertThat(poolChangelogResponses.contentSize).isEqualTo(changelogCount) + + } + + private fun assertSharingStatesSuccessful(successfulStatesCount: Int): List { + val sharingStates = gateClient.sharingState().getSharingStates( + paginationRequest = DEFAULT_PAGINATION_REQUEST, + lsaType = null, + externalIds = null + ) + val sharingStatesOkay = sharingStates.content + .filter { it.sharingStateType == SharingStateType.Success && it.bpn != null } + assertThat(sharingStatesOkay.size).isEqualTo(successfulStatesCount) + return sharingStatesOkay + } + + private fun assertEqualLegalEntity(gateVersion: LegalEntityGateInputRequest, poolVersion: LegalEntityMatchVerboseDto) { + assertThat(poolVersion.legalEntity.legalShortName).isEqualTo(gateVersion.legalEntity.legalShortName) + // assertThat(poolVersion.legalAddress.name).isEqualTo(gateVersion.legalAddress.nameParts.first()) + assertThat(poolVersion.legalAddress.physicalPostalAddress.street?.name).isEqualTo(gateVersion.legalAddress.physicalPostalAddress.street?.name) + assertThat(poolVersion.legalAddress.physicalPostalAddress.baseAddress.city).isEqualTo(gateVersion.legalAddress.physicalPostalAddress.baseAddress.city) +// assertThat(poolVersion.legalName).isEqualTo(gateVersion.legalNameParts.first()) // TODO not working, not yet persisted! + assertThat(poolVersion.legalAddress.alternativePostalAddress?.deliveryServiceNumber).isEqualTo(gateVersion.legalAddress.alternativePostalAddress?.deliveryServiceNumber) + assertThat(poolVersion.legalAddress.alternativePostalAddress?.baseAddress?.city).isEqualTo(gateVersion.legalAddress.alternativePostalAddress?.baseAddress?.city) + } + + private fun assertEqualSite(gateVersion: SiteGateInputRequest, poolVersion: SitePoolVerboseDto) { + assertThat(poolVersion.site.name).isEqualTo(gateVersion.site.nameParts.first()) + assertThat(poolVersion.site.states.map { it.description }).isEqualTo(gateVersion.site.states.map { it.description }) + } + private fun assertEqualAddress(gateVersion: AddressGateInputRequest, poolVersion: LogisticAddressVerboseDto) { assertThat(poolVersion.name).isEqualTo(gateVersion.address.nameParts.first()) assertThat(poolVersion.physicalPostalAddress.street?.name).isEqualTo(gateVersion.address.physicalPostalAddress.street?.name) diff --git a/bpdm-bridge-dummy/src/test/kotlin/com/catenax/bpdm/bridge/dummy/testdata/CommonValues.kt b/bpdm-bridge-dummy/src/test/kotlin/com/catenax/bpdm/bridge/dummy/testdata/CommonValues.kt index 2c2bbf963..084c919fc 100644 --- a/bpdm-bridge-dummy/src/test/kotlin/com/catenax/bpdm/bridge/dummy/testdata/CommonValues.kt +++ b/bpdm-bridge-dummy/src/test/kotlin/com/catenax/bpdm/bridge/dummy/testdata/CommonValues.kt @@ -22,6 +22,7 @@ package com.catenax.bpdm.bridge.dummy.testdata import com.neovisionaries.i18n.CountryCode import com.neovisionaries.i18n.LanguageCode import org.eclipse.tractusx.bpdm.common.dto.NameRegioncodeVerboseDto +import org.eclipse.tractusx.bpdm.common.dto.NameRegioncodeDto import org.eclipse.tractusx.bpdm.common.model.BusinessStateType import org.eclipse.tractusx.bpdm.common.model.CharacterSet import org.eclipse.tractusx.bpdm.common.model.ClassificationType @@ -42,6 +43,10 @@ object CommonValues { const val externalId4 = "external-4" const val externalId5 = "external-5" + val lsaTypeParam = LsaType.Address + val lsaTypeParamNotFound = LsaType.Site + val lsaNone = OptionalLsaType.None + const val externalIdSite1 = "site-external-1" const val externalIdSite2 = "site-external-2" @@ -180,6 +185,10 @@ object CommonValues { // val adminAreaLevel1RegionCode_2 = "GA" // val adminAreaLevel1Region2 = NameRegioncodeDto(adminAreaLevel1RegionCode_2, "Georgia") + val adminAreaLevel1RegionCode_1: String = "adminAreaLevel1RegionCode_1" + val adminAreaLevel1Region1: NameRegioncodeDto? = null + val adminAreaLevel1RegionCode_2: String = "adminAreaLevel1RegionCode_2" + val adminAreaLevel1Region2: NameRegioncodeDto? = null val adminAreaLevel1RegionCode_1: String? = null val adminAreaLevel1Region1: NameRegioncodeVerboseDto? = null val adminAreaLevel1RegionCode_2: String? = null diff --git a/bpdm-bridge-dummy/src/test/kotlin/com/catenax/bpdm/bridge/dummy/testdata/GateRequestValues.kt b/bpdm-bridge-dummy/src/test/kotlin/com/catenax/bpdm/bridge/dummy/testdata/GateRequestValues.kt index 815188440..c896b70bf 100644 --- a/bpdm-bridge-dummy/src/test/kotlin/com/catenax/bpdm/bridge/dummy/testdata/GateRequestValues.kt +++ b/bpdm-bridge-dummy/src/test/kotlin/com/catenax/bpdm/bridge/dummy/testdata/GateRequestValues.kt @@ -20,6 +20,9 @@ package com.catenax.bpdm.bridge.dummy.testdata import org.eclipse.tractusx.bpdm.common.dto.* +import org.eclipse.tractusx.bpdm.gate.api.model.* + +object GateRequestValues { import org.eclipse.tractusx.bpdm.gate.api.model.LogisticAddressGateDto import org.eclipse.tractusx.bpdm.gate.api.model.PhysicalPostalAddressGateDto import org.eclipse.tractusx.bpdm.gate.api.model.SiteGateDto @@ -64,6 +67,7 @@ object GateRequestValues { val name1 = NameDto(value = CommonValues.name1, shortName = CommonValues.shortName1) val leBusinessStatus1 = LegalEntityStateDto( + officialDenotation = CommonValues.businessStatusOfficialDenotation1, description = CommonValues.businessStatusOfficialDenotation1, validFrom = CommonValues.businessStatusValidFrom1, validTo = CommonValues.businessStatusValidUntil1, @@ -71,6 +75,7 @@ object GateRequestValues { ) val leBusinessStatus2 = LegalEntityStateDto( + officialDenotation = CommonValues.businessStatusOfficialDenotation2, description = CommonValues.businessStatusOfficialDenotation2, validFrom = CommonValues.businessStatusValidFrom2, validTo = CommonValues.businessStatusValidUntil2, @@ -127,6 +132,7 @@ object GateRequestValues { ), areaPart = AreaDistrictDto( administrativeAreaLevel1 = null, + administrativeAreaLevel1 = CommonValues.adminAreaLevel1RegionCode_1, //null, administrativeAreaLevel2 = CommonValues.county1, district = CommonValues.district1, ), @@ -147,6 +153,7 @@ object GateRequestValues { door = CommonValues.door2 ), areaPart = AreaDistrictDto( + administrativeAreaLevel1 = CommonValues.adminAreaLevel1RegionCode_2, administrativeAreaLevel1 = null, administrativeAreaLevel2 = CommonValues.county2, district = CommonValues.district2, @@ -274,6 +281,7 @@ object GateRequestValues { legalAddress = address1, legalNameParts = listOf(CommonValues.name1), externalId = CommonValues.externalId1, + bpn = CommonValues.bpn1 ) val legalEntityGateInputRequest2 = LegalEntityGateInputRequest( @@ -281,6 +289,9 @@ object GateRequestValues { legalAddress = address2, legalNameParts = listOf(CommonValues.name3), externalId = CommonValues.externalId2, + bpn = CommonValues.bpn2 + legalNameParts = listOf(CommonValues.name3), + externalId = CommonValues.externalId2, ) val legalEntityGateInputRequest3 = LegalEntityGateInputRequest( @@ -288,6 +299,21 @@ object GateRequestValues { legalAddress = address3, legalNameParts = listOf(CommonValues.name1), externalId = CommonValues.externalId3, + bpn = CommonValues.bpn3 + ) + + val site1 = SiteGateDto( + name = CommonValues.nameSite1, + states = listOf(siteBusinessStatus1), + mainAddress = address1 + ) + + val site2 = SiteGateDto( + name = CommonValues.nameSite2, + states = listOf(siteBusinessStatus2), + mainAddress = address2 + legalNameParts = listOf(CommonValues.name1), + externalId = CommonValues.externalId3, ) @@ -306,6 +332,7 @@ object GateRequestValues { externalId = CommonValues.externalIdSite1, legalEntityExternalId = CommonValues.externalId1, mainAddress = address1 + bpn = CommonValues.bpnSite1 ) val siteGateInputRequest2 = SiteGateInputRequest( @@ -313,6 +340,7 @@ object GateRequestValues { externalId = CommonValues.externalIdSite2, legalEntityExternalId = CommonValues.externalId2, mainAddress = address2 + bpn = CommonValues.bpnSite2 ) val addressGateInputRequest1 = AddressGateInputRequest( @@ -338,5 +366,26 @@ object GateRequestValues { siteExternalId = CommonValues.externalIdSite1, ) + name = CommonValues.name1, +// identifiers = listOf( +// AddressIdentifierDto(SaasValues.identifier1.value!!, SaasValues.identifier1.type?.technicalKey!!) +// ) + ), + externalId = CommonValues.externalIdAddress1, + legalEntityExternalId = CommonValues.externalId1, + bpn = CommonValues.bpnAddress1 + ) + + val addressGateInputRequest2 = AddressGateInputRequest( + address = address2.copy( + name = CommonValues.name2, +// identifiers = listOf( +// AddressIdentifierDto(SaasValues.identifier1.value!!, SaasValues.identifier1.type?.technicalKey!!) +// ) + ), + externalId = CommonValues.externalIdAddress2, + siteExternalId = CommonValues.externalIdSite1, + bpn = CommonValues.bpnAddress2 + ) } \ No newline at end of file diff --git a/bpdm-bridge-dummy/src/test/kotlin/com/catenax/bpdm/bridge/dummy/util/TestHelpers.kt b/bpdm-bridge-dummy/src/test/kotlin/com/catenax/bpdm/bridge/dummy/util/TestHelpers.kt index 664d14c6b..4c83b38d6 100644 --- a/bpdm-bridge-dummy/src/test/kotlin/com/catenax/bpdm/bridge/dummy/util/TestHelpers.kt +++ b/bpdm-bridge-dummy/src/test/kotlin/com/catenax/bpdm/bridge/dummy/util/TestHelpers.kt @@ -22,6 +22,7 @@ package com.catenax.bpdm.bridge.dummy.util import com.catenax.bpdm.bridge.dummy.testdata.CommonValues import jakarta.persistence.EntityManager import jakarta.persistence.EntityManagerFactory +import org.eclipse.tractusx.bpdm.common.dto.IdentifierLsaType import org.eclipse.tractusx.bpdm.common.dto.IdentifierBusinessPartnerType import org.eclipse.tractusx.bpdm.common.dto.IdentifierTypeDto import org.eclipse.tractusx.bpdm.pool.api.client.PoolApiClient