Skip to content

Commit

Permalink
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(gate): Changed Search Output logic on site/legalEntity
Browse files Browse the repository at this point in the history
alexsilva-CGI committed Jun 5, 2023
1 parent e93f02d commit 2d4b5a5
Showing 12 changed files with 167 additions and 183 deletions.
Original file line number Diff line number Diff line change
@@ -29,9 +29,7 @@ import org.eclipse.tractusx.bpdm.common.dto.request.PaginationRequest
import org.eclipse.tractusx.bpdm.common.dto.response.PageResponse
import org.eclipse.tractusx.bpdm.gate.api.model.LegalEntityGateInputRequest
import org.eclipse.tractusx.bpdm.gate.api.model.LegalEntityGateInputResponse
import org.eclipse.tractusx.bpdm.gate.api.model.LegalEntityGateOutput
import org.eclipse.tractusx.bpdm.gate.api.model.request.PaginationStartAfterRequest
import org.eclipse.tractusx.bpdm.gate.api.model.response.PageOutputResponse
import org.eclipse.tractusx.bpdm.gate.api.model.LegalEntityGateOutputResponse
import org.eclipse.tractusx.bpdm.gate.api.model.response.ValidationResponse
import org.springdoc.core.annotations.ParameterObject
import org.springframework.http.MediaType
@@ -121,9 +119,9 @@ interface GateLegalEntityApi {
@PostMapping("/output/legal-entities/search")
@PostExchange("/output/legal-entities/search")
fun getLegalEntitiesOutput(
@ParameterObject @Valid paginationRequest: PaginationStartAfterRequest,
@ParameterObject @Valid paginationRequest: PaginationRequest,
@RequestBody(required = false) externalIds: Collection<String>?
): PageOutputResponse<LegalEntityGateOutput>
): PageResponse<LegalEntityGateOutputResponse>

@Operation(
summary = "Validate a legal entity",
Original file line number Diff line number Diff line change
@@ -29,9 +29,7 @@ import org.eclipse.tractusx.bpdm.common.dto.request.PaginationRequest
import org.eclipse.tractusx.bpdm.common.dto.response.PageResponse
import org.eclipse.tractusx.bpdm.gate.api.model.SiteGateInputRequest
import org.eclipse.tractusx.bpdm.gate.api.model.SiteGateInputResponse
import org.eclipse.tractusx.bpdm.gate.api.model.SiteGateOutput
import org.eclipse.tractusx.bpdm.gate.api.model.request.PaginationStartAfterRequest
import org.eclipse.tractusx.bpdm.gate.api.model.response.PageOutputResponse
import org.eclipse.tractusx.bpdm.gate.api.model.SiteGateOutputResponse
import org.eclipse.tractusx.bpdm.gate.api.model.response.ValidationResponse
import org.springdoc.core.annotations.ParameterObject
import org.springframework.http.MediaType
@@ -121,9 +119,9 @@ interface GateSiteApi {
@PostMapping("/output/sites/search")
@PostExchange("/output/sites/search")
fun getSitesOutput(
@ParameterObject @Valid paginationRequest: PaginationStartAfterRequest,
@ParameterObject @Valid paginationRequest: PaginationRequest,
@RequestBody(required = false) externalIds: Collection<String>?
): PageOutputResponse<SiteGateOutput>
): PageResponse<SiteGateOutputResponse>

@Operation(
summary = "Validate a site",
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/*******************************************************************************
* 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.api.model

import com.fasterxml.jackson.annotation.JsonUnwrapped
import com.fasterxml.jackson.databind.annotation.JsonDeserialize
import io.swagger.v3.oas.annotations.media.Schema
import org.eclipse.tractusx.bpdm.common.dto.LegalEntityDto
import org.eclipse.tractusx.bpdm.common.service.DataClassUnwrappedJsonDeserializer
import java.time.LocalDateTime

@JsonDeserialize(using = DataClassUnwrappedJsonDeserializer::class)
@Schema(name = "LegalEntityGateOutputResponse", description = "Legal entity with external id")
data class LegalEntityGateOutputResponse(
@field:JsonUnwrapped
val legalEntity: LegalEntityDto,

@Schema(description = "ID the record has in the external system where the record originates from", required = true)
val externalId: String,

@Schema(description = "Business Partner Number")
val bpn: String?,

@Schema(description = "Time the sharing process was started according to SaaS")
val processStartedAt: LocalDateTime? = null,
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
/*******************************************************************************
* 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.api.model

import com.fasterxml.jackson.annotation.JsonUnwrapped
import com.fasterxml.jackson.databind.annotation.JsonDeserialize
import io.swagger.v3.oas.annotations.media.Schema
import org.eclipse.tractusx.bpdm.common.dto.SiteDto
import org.eclipse.tractusx.bpdm.common.service.DataClassUnwrappedJsonDeserializer
import java.time.LocalDateTime

@JsonDeserialize(using = DataClassUnwrappedJsonDeserializer::class)
@Schema(
name = "SiteGateOutputResponse", description = "Site with legal entity reference"
)
data class SiteGateOutputResponse(
@field:JsonUnwrapped
val site: SiteGateDto,

@Schema(description = "ID the record has in the external system where the record originates from")
val externalId: String,

@Schema(description = "External id of the related legal entity")
val legalEntityExternalId: String,

@Schema(description = "Business Partner Number")
val bpn: String?,

@Schema(description = "Time the sharing process was started according to SaaS")
val processStartedAt: LocalDateTime? = null,
)
Original file line number Diff line number Diff line change
@@ -24,9 +24,7 @@ import org.eclipse.tractusx.bpdm.common.dto.response.PageResponse
import org.eclipse.tractusx.bpdm.gate.api.GateLegalEntityApi
import org.eclipse.tractusx.bpdm.gate.api.model.LegalEntityGateInputRequest
import org.eclipse.tractusx.bpdm.gate.api.model.LegalEntityGateInputResponse
import org.eclipse.tractusx.bpdm.gate.api.model.LegalEntityGateOutput
import org.eclipse.tractusx.bpdm.gate.api.model.request.PaginationStartAfterRequest
import org.eclipse.tractusx.bpdm.gate.api.model.response.PageOutputResponse
import org.eclipse.tractusx.bpdm.gate.api.model.LegalEntityGateOutputResponse
import org.eclipse.tractusx.bpdm.gate.api.model.response.ValidationResponse
import org.eclipse.tractusx.bpdm.gate.config.ApiConfigProperties
import org.eclipse.tractusx.bpdm.gate.containsDuplicates
@@ -67,10 +65,10 @@ class LegalEntityController(
}

override fun getLegalEntitiesOutput(
paginationRequest: PaginationStartAfterRequest,
paginationRequest: PaginationRequest,
externalIds: Collection<String>?
): PageOutputResponse<LegalEntityGateOutput> {
return legalEntityService.getLegalEntitiesOutput(externalIds, paginationRequest.limit, paginationRequest.startAfter)
): PageResponse<LegalEntityGateOutputResponse> {
return legalEntityService.getLegalEntitiesOutput(externalIds = externalIds, page = paginationRequest.page, size = paginationRequest.size)
}

override fun validateLegalEntity(legalEntityInput: LegalEntityGateInputRequest): ValidationResponse {
Original file line number Diff line number Diff line change
@@ -24,9 +24,7 @@ import org.eclipse.tractusx.bpdm.common.dto.response.PageResponse
import org.eclipse.tractusx.bpdm.gate.api.GateSiteApi
import org.eclipse.tractusx.bpdm.gate.api.model.SiteGateInputRequest
import org.eclipse.tractusx.bpdm.gate.api.model.SiteGateInputResponse
import org.eclipse.tractusx.bpdm.gate.api.model.SiteGateOutput
import org.eclipse.tractusx.bpdm.gate.api.model.request.PaginationStartAfterRequest
import org.eclipse.tractusx.bpdm.gate.api.model.response.PageOutputResponse
import org.eclipse.tractusx.bpdm.gate.api.model.SiteGateOutputResponse
import org.eclipse.tractusx.bpdm.gate.api.model.response.ValidationResponse
import org.eclipse.tractusx.bpdm.gate.config.ApiConfigProperties
import org.eclipse.tractusx.bpdm.gate.containsDuplicates
@@ -66,8 +64,8 @@ class SiteController(
return siteService.getSites(page = paginationRequest.page, size = paginationRequest.size)
}

override fun getSitesOutput(paginationRequest: PaginationStartAfterRequest, externalIds: Collection<String>?): PageOutputResponse<SiteGateOutput> {
return siteService.getSitesOutput(externalIds, paginationRequest.limit, paginationRequest.startAfter)
override fun getSitesOutput(paginationRequest: PaginationRequest, externalIds: Collection<String>?): PageResponse<SiteGateOutputResponse> {
return siteService.getSitesOutput(externalIds = externalIds, page = paginationRequest.page, size = paginationRequest.size)
}

override fun validateSite(siteInput: SiteGateInputRequest): ValidationResponse {
Original file line number Diff line number Diff line change
@@ -26,8 +26,6 @@ import org.eclipse.tractusx.bpdm.common.exception.BpdmNotFoundException
import org.eclipse.tractusx.bpdm.common.model.OutputInputEnum
import org.eclipse.tractusx.bpdm.gate.api.model.AddressGateInputRequest
import org.eclipse.tractusx.bpdm.gate.api.model.AddressGateInputResponse
import org.eclipse.tractusx.bpdm.gate.api.model.AddressGateOutput
import org.eclipse.tractusx.bpdm.gate.api.model.response.LogisticAddressGateResponse
import org.eclipse.tractusx.bpdm.gate.api.model.AddressGateOutputResponse
import org.eclipse.tractusx.bpdm.gate.api.model.response.LsaType
import org.eclipse.tractusx.bpdm.gate.config.BpnConfigProperties
@@ -111,50 +109,6 @@ class AddressService(
}
}

// val partnerResponse = saasClient.getAddresses(limit = limit, startAfter = startAfter, externalIds = externalIds)
// val partners = partnerResponse.values
//
// val partnersWithExternalId = outputSaasMappingService.mapWithExternalId(partners)
// val augmentedPartnerResponse = saasClient.getAugmentedAddresses(externalIds = partnersWithExternalId.map { it.externalId })
// val partnersWithLocalBpn = outputSaasMappingService.mapWithLocalBpn(partnersWithExternalId, augmentedPartnerResponse.values)
//
// //Search entries in the pool with BPNs found in the local mirror
// val bpnSet = partnersWithLocalBpn.map { it.bpn }.toSet()
// val addressesByBpnMap = poolClient.searchAddresses(bpnSet).associateBy { it.bpna }
//
// if (bpnSet.size > addressesByBpnMap.size) {
// logger.warn { "Requested ${bpnSet.size} addresses from pool, but only ${addressesByBpnMap.size} were found." }
// }
//
// val partnersWithPoolBpn = partnersWithLocalBpn.filter { addressesByBpnMap[it.bpn] != null }
// val bpnByExternalIdMap = partnersWithPoolBpn.map { Pair(it.partner.externalId!!, it.bpn) }.toMap()
//
// //Evaluate the sharing status of the legal entities
// val sharingStatus = outputSaasMappingService.evaluateSharingStatus(partners, partnersWithLocalBpn, partnersWithPoolBpn)
//
// val validAddresses = sharingStatus.validExternalIds.map { externalId ->
// val bpn = bpnByExternalIdMap[externalId]!!
// val address = addressesByBpnMap[bpn]!!
// toAddressOutput(externalId, address)
// }
//
// return PageOutputResponse(
// total = partnerResponse.total,
// nextStartAfter = partnerResponse.nextStartAfter,
// content = validAddresses,
// invalidEntries = partners.size - sharingStatus.validExternalIds.size, // difference between all entries from SaaS and valid content
// pending = sharingStatus.pendingExternalIds,
// errors = sharingStatus.errors,
// )
// }

fun toAddressOutput(externalId: String, address: LogisticAddressGateResponse): AddressGateOutput {
return AddressGateOutput(
address = address,
externalId = externalId
)
}

/**
* Upsert addresses by:
*
Original file line number Diff line number Diff line change
@@ -20,17 +20,13 @@
package org.eclipse.tractusx.bpdm.gate.service

import mu.KotlinLogging
import org.eclipse.tractusx.bpdm.common.dto.response.LegalEntityResponse
import org.eclipse.tractusx.bpdm.common.dto.response.PageResponse
import org.eclipse.tractusx.bpdm.common.dto.response.PoolLegalEntityResponse
import org.eclipse.tractusx.bpdm.common.exception.BpdmNotFoundException
import org.eclipse.tractusx.bpdm.common.model.OutputInputEnum
import org.eclipse.tractusx.bpdm.gate.api.model.LegalEntityGateInputRequest
import org.eclipse.tractusx.bpdm.gate.api.model.LegalEntityGateInputResponse
import org.eclipse.tractusx.bpdm.gate.api.model.LegalEntityGateOutput
import org.eclipse.tractusx.bpdm.gate.api.model.response.LogisticAddressGateResponse
import org.eclipse.tractusx.bpdm.gate.api.model.LegalEntityGateOutputResponse
import org.eclipse.tractusx.bpdm.gate.api.model.response.LsaType
import org.eclipse.tractusx.bpdm.gate.api.model.response.PageOutputResponse
import org.eclipse.tractusx.bpdm.gate.entity.ChangelogEntry
import org.eclipse.tractusx.bpdm.gate.entity.LegalEntity
import org.eclipse.tractusx.bpdm.gate.repository.ChangelogRepository
@@ -92,69 +88,26 @@ class LegalEntityService(
* Get legal entities by first fetching legal entities from "augmented business partners" in SaaS. Augmented business partners from SaaS should contain a BPN,
* which is then used to fetch the data for the legal entities from the bpdm pool.
*/
fun getLegalEntitiesOutput(externalIds: Collection<String>?, limit: Int, startAfter: String?): PageOutputResponse<LegalEntityGateOutput> {
val partnerResponse = saasClient.getLegalEntities(limit = limit, startAfter = startAfter, externalIds = externalIds)
val partners = partnerResponse.values
fun getLegalEntitiesOutput(externalIds: Collection<String>?, page: Int, size: Int): PageResponse<LegalEntityGateOutputResponse> {

val partnersWithExternalId = outputSaasMappingService.mapWithExternalId(partners)
val augmentedPartnerResponse = saasClient.getAugmentedLegalEntities(externalIds = partnersWithExternalId.map { it.externalId })
val partnersWithLocalBpn = outputSaasMappingService.mapWithLocalBpn(partnersWithExternalId, augmentedPartnerResponse.values)
val legalEntityPage = legalEntityRepository.findByExternalIdInAndDataType(externalIds, OutputInputEnum.Output, PageRequest.of(page, size))

//Search entries in the pool with BPNs found in the local mirror
val bpnSet = partnersWithLocalBpn.map { it.bpn }.toSet()
val legalEntitiesByBpnMap = poolClient.searchLegalEntities(bpnSet).associateBy { it.legalEntity.bpnl }
val legalAddressesByBpnMap = poolClient.searchLegalAddresses(bpnSet).associateBy { it.bpnLegalEntity }

if (bpnSet.size > legalEntitiesByBpnMap.size) {
logger.warn { "Requested ${bpnSet.size} legal entities from pool, but only ${legalEntitiesByBpnMap.size} were found." }
}
if (bpnSet.size > legalAddressesByBpnMap.size) {
logger.warn { "Requested ${bpnSet.size} legal addresses from pool, but only ${legalAddressesByBpnMap.size} were found." }
}

//Filter only legal entities which can be found with their legal address in the Pool under the given local BPN
val partnersWithPoolBpn = partnersWithLocalBpn.filter { legalEntitiesByBpnMap[it.bpn] != null && legalAddressesByBpnMap[it.bpn] != null }
val bpnByExternalIdMap = partnersWithPoolBpn.associate { Pair(it.externalId, it.bpn) }
return PageResponse(
page = page,
totalElements = legalEntityPage.totalElements,
totalPages = legalEntityPage.totalPages,
contentSize = legalEntityPage.content.size,
content = toValidOutputLegalEntities(legalEntityPage),
)

//Evaluate the sharing status of the legal entities
val sharingStatus = outputSaasMappingService.evaluateSharingStatus(partners, partnersWithLocalBpn, partnersWithPoolBpn)
}

val validLegalEntities = sharingStatus.validExternalIds.map { externalId ->
val bpn = bpnByExternalIdMap[externalId]!!
val legalEntity = legalEntitiesByBpnMap[bpn]!!
val legalAddress = legalAddressesByBpnMap[bpn]!!
toLegalEntityOutput(externalId, legalEntity, legalAddress)
private fun toValidOutputLegalEntities(legalEntityPage: Page<LegalEntity>): List<LegalEntityGateOutputResponse> {
return legalEntityPage.content.map { legalEntity ->
legalEntity.toLegalEntityGateOutputResponse(legalEntity)
}

return PageOutputResponse(
total = partnerResponse.total,
nextStartAfter = partnerResponse.nextStartAfter,
content = validLegalEntities,
invalidEntries = partners.size - sharingStatus.validExternalIds.size, // difference between all entries from SaaS and valid content
pending = sharingStatus.pendingExternalIds,
errors = sharingStatus.errors,
)
}

fun toLegalEntityOutput(externalId: String, legalEntityPool: PoolLegalEntityResponse, legalAddress: LogisticAddressGateResponse): LegalEntityGateOutput =
LegalEntityGateOutput(
legalEntity = LegalEntityResponse(
bpnl = legalEntityPool.legalEntity.bpnl,
identifiers = legalEntityPool.legalEntity.identifiers,
legalShortName = legalEntityPool.legalEntity.legalShortName,
legalForm = legalEntityPool.legalEntity.legalForm,
states = legalEntityPool.legalEntity.states,
classifications = legalEntityPool.legalEntity.classifications,
relations = legalEntityPool.legalEntity.relations,
currentness = legalEntityPool.legalEntity.currentness,
createdAt = legalEntityPool.legalEntity.createdAt,
updatedAt = legalEntityPool.legalEntity.updatedAt,
),
legalAddress = legalAddress,
legalNameParts = arrayOf(legalEntityPool.legalName),
externalId = externalId
)

private fun toValidLegalEntities(legalEntityPage: Page<LegalEntity>): List<LegalEntityGateInputResponse> {
return legalEntityPage.content.map { legalEntity ->
legalEntity.LegalEntityGateInputResponse(legalEntity)
Loading

0 comments on commit 2d4b5a5

Please sign in to comment.