From 6c709db80cac1187729f33efe84b82c73c7f3e03 Mon Sep 17 00:00:00 2001 From: rschneider <97682836+rainer-exxcellent@users.noreply.github.com> Date: Tue, 24 Oct 2023 11:22:50 +0200 Subject: [PATCH] feat(pool): #556 Upsert Business Partners from Cleaning Result - refactor validation and persistence --- .../common/dto/AlternativePostalAddressDto.kt | 10 +- .../dto/IBaseAlternativePostalAddressDto.kt | 5 + .../dto/IBasePhysicalPostalAddressDto.kt | 5 + .../tractusx/bpdm/common/dto/IBaseSiteDto.kt | 3 + .../common/dto/PhysicalPostalAddressDto.kt | 10 +- .../bpdm/common/dto/RequestWithKey.kt | 25 ++ .../tractusx/bpdm/common/dto/SiteDto.kt | 12 +- .../AlternativePostalAddressVerboseDto.kt | 9 +- .../PhysicalPostalAddressVerboseDto.kt | 10 +- .../model/AlternativePostalAddressGateDto.kt | 10 +- .../api/model/PhysicalPostalAddressGateDto.kt | 10 +- .../api/model/AlternativePostalAddressDto.kt | 9 +- .../api/model/PhysicalPostalAddressDto.kt | 10 +- .../orchestrator/api/model/SiteDto.kt | 3 +- .../api/model/TaskStepReservationEntryDto.kt | 7 +- .../request/AddressPartnerCreateRequest.kt | 8 +- .../request/AddressPartnerUpdateRequest.kt | 7 +- .../LegalEntityPartnerCreateRequest.kt | 7 +- .../LegalEntityPartnerUpdateRequest.kt | 7 +- .../model/request/SitePartnerCreateRequest.kt | 7 +- .../model/request/SitePartnerUpdateRequest.kt | 7 +- .../service/BusinessPartnerBuildService.kt | 257 +++++++++--------- .../bpdm/pool/service/MetadataService.kt | 21 +- .../pool/service/RequestValidationService.kt | 147 +++++----- .../bpdm/pool/service/TaskStepBuildService.kt | 164 ++--------- .../service/TaskStepFetchAndReserveService.kt | 11 +- 26 files changed, 401 insertions(+), 380 deletions(-) create mode 100644 bpdm-common/src/main/kotlin/org/eclipse/tractusx/bpdm/common/dto/RequestWithKey.kt diff --git a/bpdm-common/src/main/kotlin/org/eclipse/tractusx/bpdm/common/dto/AlternativePostalAddressDto.kt b/bpdm-common/src/main/kotlin/org/eclipse/tractusx/bpdm/common/dto/AlternativePostalAddressDto.kt index a436bc210..231e7fefe 100644 --- a/bpdm-common/src/main/kotlin/org/eclipse/tractusx/bpdm/common/dto/AlternativePostalAddressDto.kt +++ b/bpdm-common/src/main/kotlin/org/eclipse/tractusx/bpdm/common/dto/AlternativePostalAddressDto.kt @@ -49,4 +49,12 @@ data class AlternativePostalAddressDto( override val deliveryServiceNumber: String -) : IBaseAlternativePostalAddressDto +) : IBaseAlternativePostalAddressDto { + override fun adminLevel1Key(): String? { + return administrativeAreaLevel1 + } + + override fun countryCode(): CountryCode { + return country + } +} diff --git a/bpdm-common/src/main/kotlin/org/eclipse/tractusx/bpdm/common/dto/IBaseAlternativePostalAddressDto.kt b/bpdm-common/src/main/kotlin/org/eclipse/tractusx/bpdm/common/dto/IBaseAlternativePostalAddressDto.kt index 269ff915a..6cbe666ad 100644 --- a/bpdm-common/src/main/kotlin/org/eclipse/tractusx/bpdm/common/dto/IBaseAlternativePostalAddressDto.kt +++ b/bpdm-common/src/main/kotlin/org/eclipse/tractusx/bpdm/common/dto/IBaseAlternativePostalAddressDto.kt @@ -19,6 +19,7 @@ package org.eclipse.tractusx.bpdm.common.dto +import com.neovisionaries.i18n.CountryCode import io.swagger.v3.oas.annotations.media.Schema import org.eclipse.tractusx.bpdm.common.dto.openapidescription.PostalAddressDescription import org.eclipse.tractusx.bpdm.common.model.DeliveryServiceType @@ -51,4 +52,8 @@ interface IBaseAlternativePostalAddressDto { @get:Schema(description = PostalAddressDescription.deliveryServiceNumber) val deliveryServiceNumber: String? + + fun adminLevel1Key(): String? + + fun countryCode(): CountryCode? } diff --git a/bpdm-common/src/main/kotlin/org/eclipse/tractusx/bpdm/common/dto/IBasePhysicalPostalAddressDto.kt b/bpdm-common/src/main/kotlin/org/eclipse/tractusx/bpdm/common/dto/IBasePhysicalPostalAddressDto.kt index add476881..4059e92a3 100644 --- a/bpdm-common/src/main/kotlin/org/eclipse/tractusx/bpdm/common/dto/IBasePhysicalPostalAddressDto.kt +++ b/bpdm-common/src/main/kotlin/org/eclipse/tractusx/bpdm/common/dto/IBasePhysicalPostalAddressDto.kt @@ -19,6 +19,7 @@ package org.eclipse.tractusx.bpdm.common.dto +import com.neovisionaries.i18n.CountryCode import io.swagger.v3.oas.annotations.media.Schema import org.eclipse.tractusx.bpdm.common.dto.openapidescription.PostalAddressDescription @@ -68,4 +69,8 @@ interface IBasePhysicalPostalAddressDto { @get:Schema(description = PostalAddressDescription.door) val door: String? + + fun adminLevel1Key(): String? + + fun countryCode(): CountryCode? } diff --git a/bpdm-common/src/main/kotlin/org/eclipse/tractusx/bpdm/common/dto/IBaseSiteDto.kt b/bpdm-common/src/main/kotlin/org/eclipse/tractusx/bpdm/common/dto/IBaseSiteDto.kt index 61c5dd9cf..b430de58b 100644 --- a/bpdm-common/src/main/kotlin/org/eclipse/tractusx/bpdm/common/dto/IBaseSiteDto.kt +++ b/bpdm-common/src/main/kotlin/org/eclipse/tractusx/bpdm/common/dto/IBaseSiteDto.kt @@ -26,6 +26,9 @@ import org.eclipse.tractusx.bpdm.common.dto.openapidescription.SiteDescription @Schema(description = SiteDescription.header) interface IBaseSiteDto { + @get:Schema(description = SiteDescription.name) + val name: String? + @get:ArraySchema(arraySchema = Schema(description = SiteDescription.states)) val states: Collection diff --git a/bpdm-common/src/main/kotlin/org/eclipse/tractusx/bpdm/common/dto/PhysicalPostalAddressDto.kt b/bpdm-common/src/main/kotlin/org/eclipse/tractusx/bpdm/common/dto/PhysicalPostalAddressDto.kt index 2d655f4ae..9076674ff 100644 --- a/bpdm-common/src/main/kotlin/org/eclipse/tractusx/bpdm/common/dto/PhysicalPostalAddressDto.kt +++ b/bpdm-common/src/main/kotlin/org/eclipse/tractusx/bpdm/common/dto/PhysicalPostalAddressDto.kt @@ -57,4 +57,12 @@ data class PhysicalPostalAddressDto( override val door: String? -) : IBasePhysicalPostalAddressDto +) : IBasePhysicalPostalAddressDto { + override fun adminLevel1Key(): String? { + return administrativeAreaLevel1 + } + + override fun countryCode(): CountryCode { + return country + } +} diff --git a/bpdm-common/src/main/kotlin/org/eclipse/tractusx/bpdm/common/dto/RequestWithKey.kt b/bpdm-common/src/main/kotlin/org/eclipse/tractusx/bpdm/common/dto/RequestWithKey.kt new file mode 100644 index 000000000..7d7c7076c --- /dev/null +++ b/bpdm-common/src/main/kotlin/org/eclipse/tractusx/bpdm/common/dto/RequestWithKey.kt @@ -0,0 +1,25 @@ +/******************************************************************************* + * 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.common.dto + +interface RequestWithKey { + + fun getRequestKey(): String? +} \ No newline at end of file diff --git a/bpdm-common/src/main/kotlin/org/eclipse/tractusx/bpdm/common/dto/SiteDto.kt b/bpdm-common/src/main/kotlin/org/eclipse/tractusx/bpdm/common/dto/SiteDto.kt index 65084c703..3379a3871 100644 --- a/bpdm-common/src/main/kotlin/org/eclipse/tractusx/bpdm/common/dto/SiteDto.kt +++ b/bpdm-common/src/main/kotlin/org/eclipse/tractusx/bpdm/common/dto/SiteDto.kt @@ -26,13 +26,9 @@ import org.eclipse.tractusx.bpdm.common.dto.openapidescription.SiteDescription @Schema(description = SiteDescription.header) data class SiteDto( - @get:Schema(description = SiteDescription.name) - val name: String, + override val name: String, - @ArraySchema(arraySchema = Schema(description = SiteDescription.states)) - val states: Collection = emptyList(), + override val states: Collection = emptyList(), - // TODO OpenAPI description for complex field does not work!! - @get:Schema(description = SiteDescription.mainAddress) - val mainAddress: LogisticAddressDto -) \ No newline at end of file + override val mainAddress: LogisticAddressDto +) : IBaseSiteDto \ No newline at end of file diff --git a/bpdm-common/src/main/kotlin/org/eclipse/tractusx/bpdm/common/dto/response/AlternativePostalAddressVerboseDto.kt b/bpdm-common/src/main/kotlin/org/eclipse/tractusx/bpdm/common/dto/response/AlternativePostalAddressVerboseDto.kt index 80dfb5725..0be788532 100644 --- a/bpdm-common/src/main/kotlin/org/eclipse/tractusx/bpdm/common/dto/response/AlternativePostalAddressVerboseDto.kt +++ b/bpdm-common/src/main/kotlin/org/eclipse/tractusx/bpdm/common/dto/response/AlternativePostalAddressVerboseDto.kt @@ -51,4 +51,11 @@ data class AlternativePostalAddressVerboseDto( override val deliveryServiceNumber: String -) : IBaseAlternativePostalAddressDto +) : IBaseAlternativePostalAddressDto { + override fun adminLevel1Key(): String? { + return administrativeAreaLevel1?.regionCode + } + override fun countryCode(): CountryCode { + return country.technicalKey + } +} diff --git a/bpdm-common/src/main/kotlin/org/eclipse/tractusx/bpdm/common/dto/response/PhysicalPostalAddressVerboseDto.kt b/bpdm-common/src/main/kotlin/org/eclipse/tractusx/bpdm/common/dto/response/PhysicalPostalAddressVerboseDto.kt index 4e4796ad1..ec1383a3d 100644 --- a/bpdm-common/src/main/kotlin/org/eclipse/tractusx/bpdm/common/dto/response/PhysicalPostalAddressVerboseDto.kt +++ b/bpdm-common/src/main/kotlin/org/eclipse/tractusx/bpdm/common/dto/response/PhysicalPostalAddressVerboseDto.kt @@ -63,4 +63,12 @@ data class PhysicalPostalAddressVerboseDto( override val door: String? -) : IBasePhysicalPostalAddressDto +) : IBasePhysicalPostalAddressDto { + override fun adminLevel1Key(): String? { + return administrativeAreaLevel1?.regionCode + } + + override fun countryCode(): CountryCode { + return country.technicalKey + } +} diff --git a/bpdm-gate-api/src/main/kotlin/org/eclipse/tractusx/bpdm/gate/api/model/AlternativePostalAddressGateDto.kt b/bpdm-gate-api/src/main/kotlin/org/eclipse/tractusx/bpdm/gate/api/model/AlternativePostalAddressGateDto.kt index a29fa69fd..006bdf602 100644 --- a/bpdm-gate-api/src/main/kotlin/org/eclipse/tractusx/bpdm/gate/api/model/AlternativePostalAddressGateDto.kt +++ b/bpdm-gate-api/src/main/kotlin/org/eclipse/tractusx/bpdm/gate/api/model/AlternativePostalAddressGateDto.kt @@ -48,4 +48,12 @@ data class AlternativePostalAddressGateDto( override val deliveryServiceNumber: String? = null -) : IBaseAlternativePostalAddressDto +) : IBaseAlternativePostalAddressDto { + override fun adminLevel1Key(): String? { + return administrativeAreaLevel1 + } + + override fun countryCode(): CountryCode? { + return country + } +} diff --git a/bpdm-gate-api/src/main/kotlin/org/eclipse/tractusx/bpdm/gate/api/model/PhysicalPostalAddressGateDto.kt b/bpdm-gate-api/src/main/kotlin/org/eclipse/tractusx/bpdm/gate/api/model/PhysicalPostalAddressGateDto.kt index 157e9265b..92287803d 100644 --- a/bpdm-gate-api/src/main/kotlin/org/eclipse/tractusx/bpdm/gate/api/model/PhysicalPostalAddressGateDto.kt +++ b/bpdm-gate-api/src/main/kotlin/org/eclipse/tractusx/bpdm/gate/api/model/PhysicalPostalAddressGateDto.kt @@ -59,4 +59,12 @@ data class PhysicalPostalAddressGateDto( override val door: String? = null -) : IBasePhysicalPostalAddressDto +) : IBasePhysicalPostalAddressDto { + override fun adminLevel1Key(): String? { + return administrativeAreaLevel1 + } + + override fun countryCode(): CountryCode? { + return country + } +} diff --git a/bpdm-orchestrator-api/src/main/kotlin/org/eclipse/tractusx/orchestrator/api/model/AlternativePostalAddressDto.kt b/bpdm-orchestrator-api/src/main/kotlin/org/eclipse/tractusx/orchestrator/api/model/AlternativePostalAddressDto.kt index 134ade3a8..958f99a93 100644 --- a/bpdm-orchestrator-api/src/main/kotlin/org/eclipse/tractusx/orchestrator/api/model/AlternativePostalAddressDto.kt +++ b/bpdm-orchestrator-api/src/main/kotlin/org/eclipse/tractusx/orchestrator/api/model/AlternativePostalAddressDto.kt @@ -34,4 +34,11 @@ data class AlternativePostalAddressDto( override val deliveryServiceQualifier: String? = null, override val deliveryServiceNumber: String? = null -) : IBaseAlternativePostalAddressDto +) : IBaseAlternativePostalAddressDto { + override fun adminLevel1Key(): String? { + return administrativeAreaLevel1 + } + override fun countryCode(): CountryCode? { + return country + } +} diff --git a/bpdm-orchestrator-api/src/main/kotlin/org/eclipse/tractusx/orchestrator/api/model/PhysicalPostalAddressDto.kt b/bpdm-orchestrator-api/src/main/kotlin/org/eclipse/tractusx/orchestrator/api/model/PhysicalPostalAddressDto.kt index ae4efdfdb..906b694ad 100644 --- a/bpdm-orchestrator-api/src/main/kotlin/org/eclipse/tractusx/orchestrator/api/model/PhysicalPostalAddressDto.kt +++ b/bpdm-orchestrator-api/src/main/kotlin/org/eclipse/tractusx/orchestrator/api/model/PhysicalPostalAddressDto.kt @@ -39,4 +39,12 @@ data class PhysicalPostalAddressDto( override val floor: String? = null, override val door: String? = null -) : IBasePhysicalPostalAddressDto +) : IBasePhysicalPostalAddressDto { + override fun adminLevel1Key(): String? { + return administrativeAreaLevel1 + } + + override fun countryCode(): CountryCode? { + return country + } +} diff --git a/bpdm-orchestrator-api/src/main/kotlin/org/eclipse/tractusx/orchestrator/api/model/SiteDto.kt b/bpdm-orchestrator-api/src/main/kotlin/org/eclipse/tractusx/orchestrator/api/model/SiteDto.kt index ca2d2e01e..9a926864b 100644 --- a/bpdm-orchestrator-api/src/main/kotlin/org/eclipse/tractusx/orchestrator/api/model/SiteDto.kt +++ b/bpdm-orchestrator-api/src/main/kotlin/org/eclipse/tractusx/orchestrator/api/model/SiteDto.kt @@ -31,8 +31,7 @@ data class SiteDto( @get:Schema(description = "Whether this site data is different from its golden record counterpart in the Pool") val hasChanged: Boolean? = null, - @get:Schema(description = SiteDescription.name) - val name: String? = null, + override val name: String? = null, override val states: Collection = emptyList(), diff --git a/bpdm-orchestrator-api/src/main/kotlin/org/eclipse/tractusx/orchestrator/api/model/TaskStepReservationEntryDto.kt b/bpdm-orchestrator-api/src/main/kotlin/org/eclipse/tractusx/orchestrator/api/model/TaskStepReservationEntryDto.kt index 906188cbf..5a5830681 100644 --- a/bpdm-orchestrator-api/src/main/kotlin/org/eclipse/tractusx/orchestrator/api/model/TaskStepReservationEntryDto.kt +++ b/bpdm-orchestrator-api/src/main/kotlin/org/eclipse/tractusx/orchestrator/api/model/TaskStepReservationEntryDto.kt @@ -20,6 +20,7 @@ package org.eclipse.tractusx.orchestrator.api.model import io.swagger.v3.oas.annotations.media.Schema +import org.eclipse.tractusx.bpdm.common.dto.RequestWithKey @Schema(description = "Task reservation entry") data class TaskStepReservationEntryDto( @@ -29,4 +30,8 @@ data class TaskStepReservationEntryDto( @get:Schema(description = "The business partner data to process") val businessPartner: BusinessPartnerFullDto -) +) : RequestWithKey { + override fun getRequestKey(): String? { + return taskId + } +} diff --git a/bpdm-pool-api/src/main/kotlin/org/eclipse/tractusx/bpdm/pool/api/model/request/AddressPartnerCreateRequest.kt b/bpdm-pool-api/src/main/kotlin/org/eclipse/tractusx/bpdm/pool/api/model/request/AddressPartnerCreateRequest.kt index c96f0d138..87d99e47b 100644 --- a/bpdm-pool-api/src/main/kotlin/org/eclipse/tractusx/bpdm/pool/api/model/request/AddressPartnerCreateRequest.kt +++ b/bpdm-pool-api/src/main/kotlin/org/eclipse/tractusx/bpdm/pool/api/model/request/AddressPartnerCreateRequest.kt @@ -23,6 +23,7 @@ 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.LogisticAddressDto +import org.eclipse.tractusx.bpdm.common.dto.RequestWithKey import org.eclipse.tractusx.bpdm.common.dto.openapidescription.CommonDescription import org.eclipse.tractusx.bpdm.common.dto.openapidescription.LogisticAddressDescription import org.eclipse.tractusx.bpdm.common.service.DataClassUnwrappedJsonDeserializer @@ -39,4 +40,9 @@ data class AddressPartnerCreateRequest( @Schema(description = CommonDescription.index) val index: String? -) +): RequestWithKey { + override fun getRequestKey(): String? { + return index + } +} + diff --git a/bpdm-pool-api/src/main/kotlin/org/eclipse/tractusx/bpdm/pool/api/model/request/AddressPartnerUpdateRequest.kt b/bpdm-pool-api/src/main/kotlin/org/eclipse/tractusx/bpdm/pool/api/model/request/AddressPartnerUpdateRequest.kt index ed61730ae..1b2912d76 100644 --- a/bpdm-pool-api/src/main/kotlin/org/eclipse/tractusx/bpdm/pool/api/model/request/AddressPartnerUpdateRequest.kt +++ b/bpdm-pool-api/src/main/kotlin/org/eclipse/tractusx/bpdm/pool/api/model/request/AddressPartnerUpdateRequest.kt @@ -23,6 +23,7 @@ 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.LogisticAddressDto +import org.eclipse.tractusx.bpdm.common.dto.RequestWithKey import org.eclipse.tractusx.bpdm.common.dto.openapidescription.LogisticAddressDescription import org.eclipse.tractusx.bpdm.common.service.DataClassUnwrappedJsonDeserializer @@ -35,4 +36,8 @@ data class AddressPartnerUpdateRequest( @field:JsonUnwrapped val address: LogisticAddressDto -) +): RequestWithKey { + override fun getRequestKey(): String? { + return bpna + } +} diff --git a/bpdm-pool-api/src/main/kotlin/org/eclipse/tractusx/bpdm/pool/api/model/request/LegalEntityPartnerCreateRequest.kt b/bpdm-pool-api/src/main/kotlin/org/eclipse/tractusx/bpdm/pool/api/model/request/LegalEntityPartnerCreateRequest.kt index 9e4d35ad8..55aaae534 100644 --- a/bpdm-pool-api/src/main/kotlin/org/eclipse/tractusx/bpdm/pool/api/model/request/LegalEntityPartnerCreateRequest.kt +++ b/bpdm-pool-api/src/main/kotlin/org/eclipse/tractusx/bpdm/pool/api/model/request/LegalEntityPartnerCreateRequest.kt @@ -24,6 +24,7 @@ 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.dto.LogisticAddressDto +import org.eclipse.tractusx.bpdm.common.dto.RequestWithKey import org.eclipse.tractusx.bpdm.common.dto.openapidescription.CommonDescription import org.eclipse.tractusx.bpdm.common.dto.openapidescription.LegalEntityDescription import org.eclipse.tractusx.bpdm.common.service.DataClassUnwrappedJsonDeserializer @@ -44,4 +45,8 @@ data class LegalEntityPartnerCreateRequest( @get:Schema(description = CommonDescription.index) val index: String? -) +): RequestWithKey { + override fun getRequestKey(): String? { + return index + } +} diff --git a/bpdm-pool-api/src/main/kotlin/org/eclipse/tractusx/bpdm/pool/api/model/request/LegalEntityPartnerUpdateRequest.kt b/bpdm-pool-api/src/main/kotlin/org/eclipse/tractusx/bpdm/pool/api/model/request/LegalEntityPartnerUpdateRequest.kt index 753689667..698960a7a 100644 --- a/bpdm-pool-api/src/main/kotlin/org/eclipse/tractusx/bpdm/pool/api/model/request/LegalEntityPartnerUpdateRequest.kt +++ b/bpdm-pool-api/src/main/kotlin/org/eclipse/tractusx/bpdm/pool/api/model/request/LegalEntityPartnerUpdateRequest.kt @@ -24,6 +24,7 @@ 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.dto.LogisticAddressDto +import org.eclipse.tractusx.bpdm.common.dto.RequestWithKey import org.eclipse.tractusx.bpdm.common.dto.openapidescription.LegalEntityDescription import org.eclipse.tractusx.bpdm.common.service.DataClassUnwrappedJsonDeserializer @@ -43,4 +44,8 @@ data class LegalEntityPartnerUpdateRequest( // TODO OpenAPI description for complex field does not work!! @get:Schema(description = LegalEntityDescription.legalAddress) val legalAddress: LogisticAddressDto, -) +): RequestWithKey { + override fun getRequestKey(): String? { + return bpnl + } +} diff --git a/bpdm-pool-api/src/main/kotlin/org/eclipse/tractusx/bpdm/pool/api/model/request/SitePartnerCreateRequest.kt b/bpdm-pool-api/src/main/kotlin/org/eclipse/tractusx/bpdm/pool/api/model/request/SitePartnerCreateRequest.kt index 7d81c9faa..c57b9615c 100644 --- a/bpdm-pool-api/src/main/kotlin/org/eclipse/tractusx/bpdm/pool/api/model/request/SitePartnerCreateRequest.kt +++ b/bpdm-pool-api/src/main/kotlin/org/eclipse/tractusx/bpdm/pool/api/model/request/SitePartnerCreateRequest.kt @@ -22,6 +22,7 @@ package org.eclipse.tractusx.bpdm.pool.api.model.request 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.RequestWithKey import org.eclipse.tractusx.bpdm.common.dto.SiteDto import org.eclipse.tractusx.bpdm.common.dto.openapidescription.CommonDescription import org.eclipse.tractusx.bpdm.common.dto.openapidescription.SiteDescription @@ -39,4 +40,8 @@ data class SitePartnerCreateRequest( @Schema(description = CommonDescription.index) val index: String? -) +) : RequestWithKey { + override fun getRequestKey(): String? { + return index + } +} diff --git a/bpdm-pool-api/src/main/kotlin/org/eclipse/tractusx/bpdm/pool/api/model/request/SitePartnerUpdateRequest.kt b/bpdm-pool-api/src/main/kotlin/org/eclipse/tractusx/bpdm/pool/api/model/request/SitePartnerUpdateRequest.kt index 79aa8a80e..a48f73c60 100644 --- a/bpdm-pool-api/src/main/kotlin/org/eclipse/tractusx/bpdm/pool/api/model/request/SitePartnerUpdateRequest.kt +++ b/bpdm-pool-api/src/main/kotlin/org/eclipse/tractusx/bpdm/pool/api/model/request/SitePartnerUpdateRequest.kt @@ -22,6 +22,7 @@ package org.eclipse.tractusx.bpdm.pool.api.model.request 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.RequestWithKey import org.eclipse.tractusx.bpdm.common.dto.SiteDto import org.eclipse.tractusx.bpdm.common.dto.openapidescription.SiteDescription import org.eclipse.tractusx.bpdm.common.service.DataClassUnwrappedJsonDeserializer @@ -35,4 +36,8 @@ data class SitePartnerUpdateRequest( @field:JsonUnwrapped val site: SiteDto -) +): RequestWithKey { + override fun getRequestKey(): String? { + return bpns + } +} diff --git a/bpdm-pool/src/main/kotlin/org/eclipse/tractusx/bpdm/pool/service/BusinessPartnerBuildService.kt b/bpdm-pool/src/main/kotlin/org/eclipse/tractusx/bpdm/pool/service/BusinessPartnerBuildService.kt index e7dbe507a..eebb382ad 100644 --- a/bpdm-pool/src/main/kotlin/org/eclipse/tractusx/bpdm/pool/service/BusinessPartnerBuildService.kt +++ b/bpdm-pool/src/main/kotlin/org/eclipse/tractusx/bpdm/pool/service/BusinessPartnerBuildService.kt @@ -22,6 +22,7 @@ package org.eclipse.tractusx.bpdm.pool.service import mu.KotlinLogging import org.eclipse.tractusx.bpdm.common.dto.* import org.eclipse.tractusx.bpdm.common.exception.BpdmNotFoundException +import org.eclipse.tractusx.bpdm.common.util.replace import org.eclipse.tractusx.bpdm.pool.api.model.ChangelogType import org.eclipse.tractusx.bpdm.pool.api.model.request.* import org.eclipse.tractusx.bpdm.pool.api.model.response.* @@ -29,6 +30,7 @@ import org.eclipse.tractusx.bpdm.pool.dto.AddressMetadataDto import org.eclipse.tractusx.bpdm.pool.dto.ChangelogEntryCreateRequest import org.eclipse.tractusx.bpdm.pool.dto.LegalEntityMetadataDto import org.eclipse.tractusx.bpdm.pool.entity.* +import org.eclipse.tractusx.bpdm.pool.exception.BpdmValidationException import org.eclipse.tractusx.bpdm.pool.repository.LegalEntityRepository import org.eclipse.tractusx.bpdm.pool.repository.LogisticAddressRepository import org.eclipse.tractusx.bpdm.pool.repository.SiteRepository @@ -62,9 +64,9 @@ class BusinessPartnerBuildService( logger.info { "Create ${requests.size} new legal entities" } - val errorsByRequest = requestValidationService.validateLegalEntityCreates(requests.associateWith { it.legalEntity }) { theRequest -> theRequest.index } + val errorsByRequest = requestValidationService.validateLegalEntityCreates(requests.associateWith { it.legalEntity }) val errorsByRequestAddress = - requestValidationService.validateLegalEntityCreatesAddresses(requests.associateWith { it.legalAddress }) { theRequest -> theRequest.index } + requestValidationService.validateLegalEntityCreatesAddresses(requests.associateWith { it.legalAddress }) val errors = errorsByRequest.flatMap { it.value } + errorsByRequestAddress.flatMap { it.value } val validRequests = requests.filterNot { errorsByRequest.containsKey(it) || errorsByRequestAddress.containsKey(it) } @@ -316,78 +318,6 @@ class BusinessPartnerBuildService( return addressesWithIndex.map { (address, index) -> address.toCreateResponse(index) } } - private fun createLegalEntity( - request: LegalEntityDto, - bpnL: String, - legalNameValue: String, - metadataMap: LegalEntityMetadataMapping - ): LegalEntity { - val legalName = Name( - value = legalNameValue, - shortName = request.legalShortName - ) - val legalForm = request.legalForm?.let { metadataMap.legalForms[it]!! } - - val partner = LegalEntity( - bpn = bpnL, - legalName = legalName, - legalForm = legalForm, - currentness = Instant.now().truncatedTo(ChronoUnit.MICROS), - ) - - updateLegalEntity(partner, request, legalNameValue, metadataMap) - - return partner - } - - private fun createSite( - request: SiteDto, - bpnS: String, - partner: LegalEntity - ): Site { - val site = Site( - bpn = bpnS, - name = request.name, - legalEntity = partner, - ) - - site.states.addAll(request.states.map { toSiteState(it, site) }) - - return site - } - - - private fun updateLegalEntity( - partner: LegalEntity, - request: LegalEntityDto, - legalName: String, - metadataMap: LegalEntityMetadataMapping - ) { - - partner.currentness = createCurrentnessTimestamp() - - partner.legalName = Name( - value = legalName, - shortName = request.legalShortName - ) - - partner.legalForm = request.legalForm?.let { metadataMap.legalForms[it]!! } - - partner.identifiers.clear() - partner.states.clear() - partner.classifications.clear() - - partner.states.addAll(request.states.map { toLegalEntityState(it, partner) }) - partner.identifiers.addAll(request.identifiers.map { toLegalEntityIdentifier(it, metadataMap.idTypes, partner) }) - partner.classifications.addAll(request.classifications.map { toLegalEntityClassification(it, partner) }.toSet()) - } - - private fun updateSite(site: Site, request: SiteDto) { - site.name = request.name - - site.states.clear() - site.states.addAll(request.states.map { toSiteState(it, site) }) - } private fun createLogisticAddress( dto: LogisticAddressDto, @@ -439,43 +369,6 @@ class BusinessPartnerBuildService( } } - private fun createPhysicalAddress(physicalAddress: PhysicalPostalAddressDto, regions: Map): PhysicalPostalAddress { - return PhysicalPostalAddress( - geographicCoordinates = physicalAddress.geographicCoordinates?.let { toEntity(it) }, - country = physicalAddress.country, - administrativeAreaLevel1 = regions[physicalAddress.administrativeAreaLevel1], - administrativeAreaLevel2 = physicalAddress.administrativeAreaLevel2, - administrativeAreaLevel3 = physicalAddress.administrativeAreaLevel3, - postCode = physicalAddress.postalCode, - city = physicalAddress.city, - districtLevel1 = physicalAddress.district, - street = physicalAddress.street?.let { createStreet(it) }, - companyPostCode = physicalAddress.companyPostalCode, - industrialZone = physicalAddress.industrialZone, - building = physicalAddress.building, - floor = physicalAddress.floor, - door = physicalAddress.door - ) - } - - private fun createAlternativeAddress(alternativeAddress: AlternativePostalAddressDto, regions: Map): AlternativePostalAddress { - return AlternativePostalAddress( - geographicCoordinates = alternativeAddress.geographicCoordinates?.let { toEntity(it) }, - country = alternativeAddress.country, - administrativeAreaLevel1 = regions[alternativeAddress.administrativeAreaLevel1], - postCode = alternativeAddress.postalCode, - city = alternativeAddress.city, - deliveryServiceType = alternativeAddress.deliveryServiceType, - deliveryServiceNumber = alternativeAddress.deliveryServiceNumber, - deliveryServiceQualifier = alternativeAddress.deliveryServiceQualifier - ) - } - - fun toEntity(dto: GeoCoordinateDto): GeographicCoordinate { - return GeographicCoordinate(dto.latitude, dto.longitude, dto.altitude) - } - - private fun LegalEntityMetadataDto.toMapping() = LegalEntityMetadataMapping( idTypes = idTypes.associateBy { it.technicalKey }, @@ -505,15 +398,6 @@ class BusinessPartnerBuildService( return Instant.now().truncatedTo(ChronoUnit.MICROS) } - fun createStreet(dto: IBaseStreetDto): Street { - return Street( - name = dto.name, - houseNumber = dto.houseNumber, - milestone = dto.milestone, - direction = dto.direction - ) - } - fun toLegalEntityState(dto: IBaseLegalEntityStateDto, legalEntity: LegalEntity): LegalEntityState { return LegalEntityState( description = dto.description, @@ -544,11 +428,14 @@ class BusinessPartnerBuildService( ) } - fun toLegalEntityClassification(dto: ClassificationDto, partner: LegalEntity): LegalEntityClassification { + fun toLegalEntityClassification(dto: IBaseClassificationDto, partner: LegalEntity): LegalEntityClassification { + + val dtoType = dto.type ?: throw BpdmValidationException(TaskStepBuildService.CleaningError.CLASSIFICATION_TYPE_IS_NULL.message) + return LegalEntityClassification( value = dto.value, code = dto.code, - type = dto.type, + type = dtoType, legalEntity = partner ) } @@ -578,6 +465,132 @@ class BusinessPartnerBuildService( ) } + fun updateSite(site: Site, siteDto: IBaseSiteDto) { + + val name = siteDto.name ?: throw BpdmValidationException(TaskStepBuildService.CleaningError.SITE_NAME_IS_NULL.message) + + site.name = name + + site.states.clear() + site.states.addAll(siteDto.states + .map { toSiteState(it, site) }) + } + + fun createSite( + siteDto: IBaseSiteDto, + bpnS: String, + partner: LegalEntity + ): Site { + + val name = siteDto.name ?: throw BpdmValidationException(TaskStepBuildService.CleaningError.SITE_NAME_IS_NULL.message) + + val site = Site( bpn = bpnS, name = name, legalEntity = partner) + + site.states.addAll(siteDto.states + .map { toSiteState(it, site) }) + + return site + } + + fun createLegalEntity( + legalEntityDto: IBaseLegalEntityDto, + bpnL: String, + legalNameValue: String?, + metadataMap: BusinessPartnerBuildService.LegalEntityMetadataMapping + ): LegalEntity { + + if (legalNameValue == null) { + throw BpdmValidationException(TaskStepBuildService.CleaningError.LEGAL_NAME_IS_NULL.message) + } + + // it has to be validated that the legalForm exits + val legalForm = legalEntityDto.legalForm?.let { metadataMap.legalForms[it]!! } + val legalName = Name(value = legalNameValue, shortName = legalEntityDto.legalShortName) + val newLegalEntity = LegalEntity( + bpn = bpnL, + legalName = legalName, + legalForm = legalForm, + currentness = Instant.now().truncatedTo(ChronoUnit.MICROS), + ) + BusinessPartnerBuildService.updateLegalEntity(newLegalEntity, legalEntityDto, legalNameValue, metadataMap) + + return newLegalEntity + } + fun updateLegalEntity( + legalEntity: LegalEntity, + legalEntityDto: IBaseLegalEntityDto, + legalName: String?, + metadataMap: LegalEntityMetadataMapping + ) { + if(legalName == null) { + throw BpdmValidationException(TaskStepBuildService.CleaningError.LEGAL_NAME_IS_NULL.message) + } + + legalEntity.currentness = createCurrentnessTimestamp() + + legalEntity.legalName = Name(value = legalName, shortName = legalEntityDto.legalShortName) + + legalEntity.legalForm = legalEntityDto.legalForm?.let { metadataMap.legalForms[it]!! } + + legalEntity.identifiers.replace(legalEntityDto.identifiers.map { toLegalEntityIdentifier(it, metadataMap.idTypes, legalEntity) }) + legalEntity.states.replace(legalEntityDto.states.map { toLegalEntityState(it, legalEntity) }) + legalEntity.classifications.replace( legalEntityDto.classifications.map { toLegalEntityClassification(it, legalEntity) }.toSet() + ) + } + + fun createPhysicalAddress(physicalAddress: IBasePhysicalPostalAddressDto, regions: Map): PhysicalPostalAddress { + + if (physicalAddress.countryCode() == null || physicalAddress.city == null) { + throw BpdmValidationException(TaskStepBuildService.CleaningError.COUNTRY_CITY_IS_NULL.message) + } + + return PhysicalPostalAddress( + geographicCoordinates = physicalAddress.geographicCoordinates?.let { GeographicCoordinate(it.latitude, it.longitude, it.altitude) }, + country = physicalAddress.countryCode()!!, + administrativeAreaLevel1 = regions[physicalAddress.administrativeAreaLevel1], + administrativeAreaLevel2 = physicalAddress.administrativeAreaLevel2, + administrativeAreaLevel3 = physicalAddress.administrativeAreaLevel3, + postCode = physicalAddress.postalCode, + city = physicalAddress.city!!, + districtLevel1 = physicalAddress.district, + street = physicalAddress.street?.let { + Street( + name = it.name, + houseNumber = it.houseNumber, + milestone = it.milestone, + direction = it.direction + ) + }, + companyPostCode = physicalAddress.companyPostalCode, + industrialZone = physicalAddress.industrialZone, + building = physicalAddress.building, + floor = physicalAddress.floor, + door = physicalAddress.door + ) + } + + fun createAlternativeAddress(alternativeAddress: IBaseAlternativePostalAddressDto, regions: Map): AlternativePostalAddress { + + if (alternativeAddress.countryCode() == null || alternativeAddress.city == null || + alternativeAddress.deliveryServiceType == null || alternativeAddress.deliveryServiceNumber == null + ) { + + throw BpdmValidationException(TaskStepBuildService.CleaningError.ALTERNATIVE_ADDRESS_DATA_IS_NULL.message) + } + + return AlternativePostalAddress( + geographicCoordinates = alternativeAddress.geographicCoordinates?.let { GeographicCoordinate(it.latitude, it.longitude, it.altitude) }, + country = alternativeAddress.countryCode()!!, + administrativeAreaLevel1 = regions[alternativeAddress.administrativeAreaLevel1], + postCode = alternativeAddress.postalCode, + city = alternativeAddress.city!!, + deliveryServiceType = alternativeAddress.deliveryServiceType!!, + deliveryServiceNumber = alternativeAddress.deliveryServiceNumber!!, + deliveryServiceQualifier = alternativeAddress.deliveryServiceQualifier + ) + } } + + } \ No newline at end of file diff --git a/bpdm-pool/src/main/kotlin/org/eclipse/tractusx/bpdm/pool/service/MetadataService.kt b/bpdm-pool/src/main/kotlin/org/eclipse/tractusx/bpdm/pool/service/MetadataService.kt index 79ef0c647..c2daacf59 100644 --- a/bpdm-pool/src/main/kotlin/org/eclipse/tractusx/bpdm/pool/service/MetadataService.kt +++ b/bpdm-pool/src/main/kotlin/org/eclipse/tractusx/bpdm/pool/service/MetadataService.kt @@ -156,31 +156,14 @@ class MetadataService( val idTypeKeys = requests.flatMap { it.identifiers }.map { it.type }.toSet() val idTypes = identifierTypeRepository.findByBusinessPartnerTypeAndTechnicalKeyIn(IdentifierBusinessPartnerType.ADDRESS, idTypeKeys) - val regionKeys = requests.mapNotNull { administrativeAreaLevel1ToString(it.physicalPostalAddress?.administrativeAreaLevel1) } - .plus(requests.mapNotNull { administrativeAreaLevel1ToString(it.alternativePostalAddress?.administrativeAreaLevel1) }) + val regionKeys = requests.mapNotNull { it.physicalPostalAddress?.adminLevel1Key() } + .plus(requests.mapNotNull { it.alternativePostalAddress?.adminLevel1Key() }) .toSet() val regions = regionRepository.findByRegionCodeIn(regionKeys) return AddressMetadataDto(idTypes, regions) } - private fun administrativeAreaLevel1ToString(administrativeAreaLevel1: Any?): String? { - - return when (administrativeAreaLevel1) { - is RegionDto -> { - administrativeAreaLevel1.regionCode - } - - is String -> { - administrativeAreaLevel1 - } - - else -> { - null; - } - } - } - /** * If no country rule exists use default rules */ diff --git a/bpdm-pool/src/main/kotlin/org/eclipse/tractusx/bpdm/pool/service/RequestValidationService.kt b/bpdm-pool/src/main/kotlin/org/eclipse/tractusx/bpdm/pool/service/RequestValidationService.kt index 1bc4cbc3e..9e4196f07 100644 --- a/bpdm-pool/src/main/kotlin/org/eclipse/tractusx/bpdm/pool/service/RequestValidationService.kt +++ b/bpdm-pool/src/main/kotlin/org/eclipse/tractusx/bpdm/pool/service/RequestValidationService.kt @@ -19,7 +19,10 @@ package org.eclipse.tractusx.bpdm.pool.service -import org.eclipse.tractusx.bpdm.common.dto.* +import org.eclipse.tractusx.bpdm.common.dto.BusinessPartnerType +import org.eclipse.tractusx.bpdm.common.dto.IBaseLegalEntityDto +import org.eclipse.tractusx.bpdm.common.dto.IBaseLogisticAddressDto +import org.eclipse.tractusx.bpdm.common.dto.RequestWithKey import org.eclipse.tractusx.bpdm.common.util.findDuplicates import org.eclipse.tractusx.bpdm.pool.api.model.request.* import org.eclipse.tractusx.bpdm.pool.api.model.response.* @@ -39,9 +42,9 @@ class RequestValidationService( private val metadataService: MetadataService ) { - fun validateLegalEntityCreates( - legalEntitiesByRequest: Map, entityKeyFunc : (IRequest) -> String? - ): Map>> { + fun validateLegalEntityCreates( + legalEntitiesByRequest: Map + ): Map>> { val legalEntityRequests = legalEntitiesByRequest.values val legalEntityMetadata = metadataService.getMetadata(legalEntityRequests).toKeys() @@ -52,58 +55,58 @@ class RequestValidationService( val request = it.key val validationErrors = - validateLegalFormExists(legalEntity - , legalEntityMetadata.legalForms - , LegalEntityCreateError.LegalFormNotFound - , entityKeyFunc(request) - ) + - validateIdentifierTypesExists( - legalEntity, - legalEntityMetadata.idTypes, - LegalEntityCreateError.LegalEntityIdentifierNotFound, - entityKeyFunc(request) + validateLegalFormExists( + legalEntity, legalEntityMetadata.legalForms, LegalEntityCreateError.LegalFormNotFound, request ) + - validateLegalEntityIdentifiersDuplicated( - legalEntity = legalEntity, - existingIdentifiers = legalEntityDuplicateIdentifierCandidates, - bpn = null, - error = LegalEntityCreateError.LegalEntityDuplicateIdentifier, - entityKey = entityKeyFunc(request) - ) + validateIdentifierTypesExists( + legalEntity, + legalEntityMetadata.idTypes, + LegalEntityCreateError.LegalEntityIdentifierNotFound, + request + ) + + validateLegalEntityIdentifiersDuplicated( + legalEntity = legalEntity, + existingIdentifiers = legalEntityDuplicateIdentifierCandidates, + bpn = null, + error = LegalEntityCreateError.LegalEntityDuplicateIdentifier, + entityKey = request + ) request to validationErrors }.toMap() .filterValues { it.isNotEmpty() } } - fun validateLegalEntityCreatesAddresses( - addressByRequest: Map, entityKeyFunc : (IRequest) -> String? - ): Map>> { + fun validateLegalEntityCreatesAddresses( + addressByRequest: Map + ): Map>> { - val legalAddressRequests = addressByRequest.values + val legalAddressRequests = addressByRequest.values val addressDuplicateIdentifierCandidates = getAddressDuplicateIdentifierCandidates(legalAddressRequests) val addressMetadata = metadataService.getMetadata(legalAddressRequests).toKeys() - return addressByRequest.map{ + return addressByRequest.map { val legalAddress = it.value val request = it.key val validationErrors = - validateRegionExists(legalAddress, - addressMetadata.regions, - LegalEntityCreateError.LegalAddressRegionNotFound, - entityKeyFunc(request)) + + validateRegionExists( + legalAddress, + addressMetadata.regions, + LegalEntityCreateError.LegalAddressRegionNotFound, + request + ) + validateIdentifierTypesExists( legalAddress, addressMetadata.idTypes, LegalEntityCreateError.LegalAddressIdentifierNotFound, - entityKeyFunc(request) + request ) + validateAddressIdentifiersDuplicated( address = legalAddress, existingIdentifiers = addressDuplicateIdentifierCandidates, bpn = null, error = LegalEntityCreateError.LegalAddressDuplicateIdentifier, - entityKey = entityKeyFunc(request) + entityKey = request ) request to validationErrors }.toMap() @@ -130,33 +133,33 @@ class RequestValidationService( val legalAddress = request.legalAddress val validationErrors = - validateLegalFormExists(legalEntity, legalEntityMetadata.legalForms, LegalEntityUpdateError.LegalFormNotFound, request.bpnl) + + validateLegalFormExists(legalEntity, legalEntityMetadata.legalForms, LegalEntityUpdateError.LegalFormNotFound, request) + validateIdentifierTypesExists( legalEntity, legalEntityMetadata.idTypes, LegalEntityUpdateError.LegalEntityIdentifierNotFound, - request.bpnl + request ) + - validateRegionExists(legalAddress, addressMetadata.regions, LegalEntityUpdateError.LegalAddressRegionNotFound, request.bpnl) + + validateRegionExists(legalAddress, addressMetadata.regions, LegalEntityUpdateError.LegalAddressRegionNotFound, request) + validateIdentifierTypesExists( legalAddress, addressMetadata.idTypes, LegalEntityUpdateError.LegalAddressIdentifierNotFound, - request.bpnl + request ) + validateLegalEntityIdentifiersDuplicated( legalEntity = legalEntity, existingIdentifiers = legalEntityDuplicateIdentifierCandidates, bpn = request.bpnl, error = LegalEntityUpdateError.LegalEntityDuplicateIdentifier, - entityKey = request.bpnl + entityKey = request ) + validateAddressIdentifiersDuplicated( address = legalAddress, existingIdentifiers = addressDuplicateIdentifierCandidates, bpn = request.bpnl, error = LegalEntityUpdateError.LegalAddressDuplicateIdentifier, - entityKey = request.bpnl + entityKey = request ) + validateUpdateBpnExists(request.bpnl, existingLegalEntityBpns, LegalEntityUpdateError.LegalEntityNotFound) @@ -180,15 +183,15 @@ class RequestValidationService( return requests.flatMap { request -> val mainAddress = request.site.mainAddress - val validationErrors = validateRegionExists(mainAddress, addressMetadata.regions, SiteCreateError.MainAddressRegionNotFound, request.index) + - validateIdentifierTypesExists(mainAddress, addressMetadata.idTypes, SiteCreateError.MainAddressIdentifierNotFound, request.index) + + val validationErrors = validateRegionExists(mainAddress, addressMetadata.regions, SiteCreateError.MainAddressRegionNotFound, request) + + validateIdentifierTypesExists(mainAddress, addressMetadata.idTypes, SiteCreateError.MainAddressIdentifierNotFound, request) + validateParentBpnExists(request.bpnlParent, request.index, existingParentBpns, SiteCreateError.LegalEntityNotFound) + validateAddressIdentifiersDuplicated( address = mainAddress, existingIdentifiers = addressDuplicateIdentifierCandidates, bpn = null, error = SiteCreateError.MainAddressDuplicateIdentifier, - entityKey = request.index + entityKey = request ) validationErrors.map { Pair(request, it) } @@ -211,15 +214,15 @@ class RequestValidationService( return requests.flatMap { request -> val mainAddress = request.site.mainAddress - val validationErrors = validateRegionExists(mainAddress, addressMetadata.regions, SiteUpdateError.MainAddressRegionNotFound, request.bpns) + - validateIdentifierTypesExists(mainAddress, addressMetadata.idTypes, SiteUpdateError.MainAddressIdentifierNotFound, request.bpns) + + val validationErrors = validateRegionExists(mainAddress, addressMetadata.regions, SiteUpdateError.MainAddressRegionNotFound, request) + + validateIdentifierTypesExists(mainAddress, addressMetadata.idTypes, SiteUpdateError.MainAddressIdentifierNotFound, request) + validateUpdateBpnExists(request.bpns, existingSiteBpns, SiteUpdateError.SiteNotFound) + validateAddressIdentifiersDuplicated( address = mainAddress, existingIdentifiers = addressDuplicateIdentifierCandidates, bpn = request.bpns, error = SiteUpdateError.MainAddressDuplicateIdentifier, - entityKey = request.bpns + entityKey = request ) validationErrors.map { Pair(request, it) } @@ -249,14 +252,14 @@ class RequestValidationService( val address = request.address val validationErrors = validateAddressParent(request, type, existingLegalEntities, existingSites) + - validateRegionExists(address, addressMetadata.regions, AddressCreateError.RegionNotFound, request.index) + - validateIdentifierTypesExists(address, addressMetadata.idTypes, AddressCreateError.IdentifierNotFound, request.index) + + validateRegionExists(address, addressMetadata.regions, AddressCreateError.RegionNotFound, request) + + validateIdentifierTypesExists(address, addressMetadata.idTypes, AddressCreateError.IdentifierNotFound, request) + validateAddressIdentifiersDuplicated( address = address, existingIdentifiers = addressDuplicateIdentifierCandidates, bpn = null, error = AddressCreateError.AddressDuplicateIdentifier, - entityKey = request.index + entityKey = request ) validationErrors.map { Pair(request, it) } @@ -279,15 +282,15 @@ class RequestValidationService( return requests.flatMap { request -> val address = request.address - val validationErrors = validateRegionExists(address, addressMetadata.regions, AddressUpdateError.RegionNotFound, request.bpna) + - validateIdentifierTypesExists(address, addressMetadata.idTypes, AddressUpdateError.IdentifierNotFound, request.bpna) + + val validationErrors = validateRegionExists(address, addressMetadata.regions, AddressUpdateError.RegionNotFound, request) + + validateIdentifierTypesExists(address, addressMetadata.idTypes, AddressUpdateError.IdentifierNotFound, request) + validateUpdateBpnExists(request.bpna, existingAddressBpns, AddressUpdateError.AddressNotFound) + validateAddressIdentifiersDuplicated( address = address, existingIdentifiers = addressDuplicateIdentifierCandidates, bpn = request.bpna, error = AddressUpdateError.AddressDuplicateIdentifier, - entityKey = request.bpna + entityKey = request ) validationErrors.map { Pair(request, it) } @@ -296,7 +299,12 @@ class RequestValidationService( } - private fun validateIdentifierTypesExists(request: IBaseLegalEntityDto, existingTypes: Set, error: ERROR, entityKey: String?) + private fun validateIdentifierTypesExists( + request: IBaseLegalEntityDto, + existingTypes: Set, + error: ERROR, + entityKey: RequestWithKey + ) : Collection> { val requestedTypes = request.identifiers.map { it.type } val missingTypes = requestedTypes - existingTypes @@ -305,24 +313,34 @@ class RequestValidationService( ErrorInfo( error, "Legal Entity Identifier Type '$it' does not exist", - entityKey + entityKey.getRequestKey() ) } } - private fun validateLegalFormExists(request: IBaseLegalEntityDto, existingLegalForms: Set, error: ERROR, entityKey: String?) + private fun validateLegalFormExists( + request: IBaseLegalEntityDto, + existingLegalForms: Set, + error: ERROR, + entityKey: RequestWithKey + ) : Collection> { if (request.legalForm != null) { if (!existingLegalForms.contains(request.legalForm)) { - return listOf(ErrorInfo(error, "Legal Form '${request.legalForm}' does not exist", entityKey)) + return listOf(ErrorInfo(error, "Legal Form '${request.legalForm}' does not exist", entityKey.getRequestKey())) } } return emptyList() } - private fun validateIdentifierTypesExists(request: IBaseLogisticAddressDto, existingTypes: Set, error: ERROR, entityKey: String?) + private fun validateIdentifierTypesExists( + request: IBaseLogisticAddressDto, + existingTypes: Set, + error: ERROR, + entityKey: RequestWithKey + ) : Collection> { val requestedTypes = request.identifiers.map { it.type } val missingTypes = requestedTypes - existingTypes @@ -331,12 +349,17 @@ class RequestValidationService( ErrorInfo( error, "Address Identifier Type '$it' does not exist", - entityKey + entityKey.getRequestKey() ) } } - private fun validateRegionExists(request: IBaseLogisticAddressDto, existingRegions: Set, error: ERROR, entityKey: String?) + private fun validateRegionExists( + request: IBaseLogisticAddressDto, + existingRegions: Set, + error: ERROR, + entityKey: RequestWithKey + ) : Collection> { val requestedTypes = listOfNotNull( request.physicalPostalAddress?.administrativeAreaLevel1, @@ -349,7 +372,7 @@ class RequestValidationService( ErrorInfo( error, "Address Identifier Type '$it' does not exist", - entityKey + entityKey.getRequestKey() ) } } @@ -403,13 +426,13 @@ class RequestValidationService( existingIdentifiers: Map, bpn: String?, error: ERROR, - entityKey: String? + entityKey: RequestWithKey ): Collection> { return legalEntity.identifiers.mapNotNull { val identifierPair = IdentifierCandidateKey(type = it.type, value = it.value) existingIdentifiers[identifierPair]?.let { candidate -> if (candidate.bpn === null || candidate.bpn != bpn) - ErrorInfo(error, "Duplicate Legal Entity Identifier: Value '${it.value}' of type '${it.type}'", entityKey) + ErrorInfo(error, "Duplicate Legal Entity Identifier: Value '${it.value}' of type '${it.type}'", entityKey.getRequestKey()) else null } @@ -421,13 +444,13 @@ class RequestValidationService( existingIdentifiers: Map, bpn: String?, error: ERROR, - entityKey: String? + entityKey: RequestWithKey ): Collection> { return address.identifiers.mapNotNull { val identifierPair = IdentifierCandidateKey(type = it.type, value = it.value) existingIdentifiers[identifierPair]?.let { candidate -> if (candidate.bpn === null || candidate.bpn != bpn) - ErrorInfo(error, "Duplicate Address Identifier: Value '${it.value}' of type '${it.type}'", entityKey) + ErrorInfo(error, "Duplicate Address Identifier: Value '${it.value}' of type '${it.type}'", entityKey.getRequestKey()) else null } 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 424694aa7..470cca4f6 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 @@ -21,7 +21,6 @@ package org.eclipse.tractusx.bpdm.pool.service import jakarta.transaction.Transactional import org.eclipse.tractusx.bpdm.common.dto.BusinessPartnerType -import org.eclipse.tractusx.bpdm.common.util.replace import org.eclipse.tractusx.bpdm.pool.api.model.ChangelogType import org.eclipse.tractusx.bpdm.pool.dto.AddressMetadataDto import org.eclipse.tractusx.bpdm.pool.dto.ChangelogEntryCreateRequest @@ -33,8 +32,6 @@ 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 -import java.time.temporal.ChronoUnit @Service class TaskStepBuildService( @@ -60,8 +57,8 @@ class TaskStepBuildService( SITE_NAME_IS_NULL("Site name is null"), INVALID_LOGISTIC_ADDRESS_BPN("Invalid Logistic Address BPN"), INVALID_LEGAL_ENTITY_BPN("Invalid legal entity BPN"), - INVALID_SITE_BPN("Invalid site BPN") - + INVALID_SITE_BPN("Invalid site BPN"), + CLASSIFICATION_TYPE_IS_NULL("Classification type is null") } @Transactional @@ -72,7 +69,7 @@ class TaskStepBuildService( var addressResult: LogisticAddressDto? = null val legalEntity = upsertLegalEntity(businessPartnerDto.legalEntity, taskEntryBpnMapping) - var genericBpnA= legalEntity.legalAddress.bpn + var genericBpnA = legalEntity.legalAddress.bpn var siteEntity: Site? = null if (businessPartnerDto.site != null) { @@ -82,7 +79,7 @@ class TaskStepBuildService( ) genericBpnA = siteEntity.mainAddress.bpn } - var addressEntity: LogisticAddress? = null + val addressEntity: LogisticAddress? if (businessPartnerDto.address != null) { addressEntity = upsertLogisticAddress(businessPartnerDto.address, legalEntity, siteEntity, taskEntryBpnMapping) addressResult = businessPartnerDto.address!!.copy( @@ -183,8 +180,13 @@ class TaskStepBuildService( bpn = bpn, legalEntity = null, site = null, - physicalPostalAddress = createPhysicalAddress(dto.physicalPostalAddress!!, addressMetadataMap.regions), - alternativePostalAddress = dto.alternativePostalAddress?.let { createAlternativeAddress(it, addressMetadataMap.regions) }, + physicalPostalAddress = BusinessPartnerBuildService.createPhysicalAddress(dto.physicalPostalAddress!!, addressMetadataMap.regions), + alternativePostalAddress = dto.alternativePostalAddress?.let { + BusinessPartnerBuildService.createAlternativeAddress( + it, + addressMetadataMap.regions + ) + }, name = dto.name ) updateAddressIdentifiersAndStates(address, dto, addressMetadataMap.idTypes) @@ -200,8 +202,8 @@ class TaskStepBuildService( } address.name = dto.name - address.physicalPostalAddress = createPhysicalAddress(dto.physicalPostalAddress!!, metadataMap.regions) - address.alternativePostalAddress = dto.alternativePostalAddress?.let { createAlternativeAddress(it, metadataMap.regions) } + address.physicalPostalAddress = BusinessPartnerBuildService.createPhysicalAddress(dto.physicalPostalAddress!!, metadataMap.regions) + address.alternativePostalAddress = dto.alternativePostalAddress?.let { BusinessPartnerBuildService.createAlternativeAddress(it, metadataMap.regions) } updateAddressIdentifiersAndStates(address, dto, metadataMap.idTypes) } @@ -235,106 +237,6 @@ class TaskStepBuildService( } } - private fun createAlternativeAddress(alternativeAddress: AlternativePostalAddressDto, regions: Map): AlternativePostalAddress { - - if (alternativeAddress.country == null || alternativeAddress.city == null || - alternativeAddress.deliveryServiceType == null || alternativeAddress.deliveryServiceNumber == null - ) { - - throw BpdmValidationException(CleaningError.ALTERNATIVE_ADDRESS_DATA_IS_NULL.message) - } - - return AlternativePostalAddress( - geographicCoordinates = alternativeAddress.geographicCoordinates?.let { GeographicCoordinate(it.latitude, it.longitude, it.altitude) }, - country = alternativeAddress.country!!, - administrativeAreaLevel1 = regions[alternativeAddress.administrativeAreaLevel1], - postCode = alternativeAddress.postalCode, - city = alternativeAddress.city!!, - deliveryServiceType = alternativeAddress.deliveryServiceType!!, - deliveryServiceNumber = alternativeAddress.deliveryServiceNumber!!, - deliveryServiceQualifier = alternativeAddress.deliveryServiceQualifier - ) - } - - private fun createPhysicalAddress(physicalAddress: PhysicalPostalAddressDto, regions: Map): PhysicalPostalAddress { - - if (physicalAddress.country == null || physicalAddress.city == null) { - throw BpdmValidationException(CleaningError.COUNTRY_CITY_IS_NULL.message) - } - - return PhysicalPostalAddress( - geographicCoordinates = physicalAddress.geographicCoordinates?.let { GeographicCoordinate(it.latitude, it.longitude, it.altitude) }, - country = physicalAddress.country!!, - administrativeAreaLevel1 = regions[physicalAddress.administrativeAreaLevel1], - administrativeAreaLevel2 = physicalAddress.administrativeAreaLevel2, - administrativeAreaLevel3 = physicalAddress.administrativeAreaLevel3, - postCode = physicalAddress.postalCode, - city = physicalAddress.city!!, - districtLevel1 = physicalAddress.district, - street = physicalAddress.street?.let { - Street( - name = it.name, - houseNumber = it.houseNumber, - milestone = it.milestone, - direction = it.direction - ) - }, - companyPostCode = physicalAddress.companyPostalCode, - industrialZone = physicalAddress.industrialZone, - building = physicalAddress.building, - floor = physicalAddress.floor, - door = physicalAddress.door - ) - } - - private fun createLegalEntity( - legalEntityDto: LegalEntityDto, - bpnL: String, - metadataMap: BusinessPartnerBuildService.LegalEntityMetadataMapping - ): LegalEntity { - - if (legalEntityDto.legalName == null) { - throw BpdmValidationException(CleaningError.LEGAL_NAME_IS_NULL.message) - } - - // it has to be validated that the legalForm exits - val legalForm = legalEntityDto.legalForm?.let { metadataMap.legalForms[it]!! } - val legalName = Name(value = legalEntityDto.legalName!!, shortName = legalEntityDto.legalShortName) - val newLegalEntity = LegalEntity( - bpn = bpnL, - legalName = legalName, - legalForm = legalForm, - currentness = Instant.now().truncatedTo(ChronoUnit.MICROS), - ) - updateLegalEntity(newLegalEntity, legalEntityDto, - legalEntityDto.identifiers.map { BusinessPartnerBuildService.toLegalEntityIdentifier(it, metadataMap.idTypes, newLegalEntity) }) - - return newLegalEntity - } - - private fun updateLegalEntity( - legalEntity: LegalEntity, - legalEntityDto: LegalEntityDto, - identifiers: List - ) { - val legalName = legalEntityDto.legalName ?: throw BpdmValidationException(CleaningError.LEGAL_NAME_IS_NULL.message) - - legalEntity.currentness = BusinessPartnerBuildService.createCurrentnessTimestamp() - - legalEntity.legalName = Name(value = legalName, shortName = legalEntityDto.legalShortName) - - legalEntity.identifiers.replace(identifiers) - - legalEntity.states.replace(legalEntityDto.states - .map { BusinessPartnerBuildService.toLegalEntityState(it, legalEntity) }) - - legalEntity.classifications.replace( - legalEntityDto.classifications - .map { BusinessPartnerBuildService.toLegalEntityClassification(it, legalEntity) }.toSet() - ) - } - - fun upsertLegalEntity( legalEntityDto: LegalEntityDto?, taskEntryBpnMapping: TaskEntryBpnMapping ): LegalEntity { @@ -348,7 +250,7 @@ class TaskStepBuildService( val upsertLe = if (bpn == null) { val bpnL = bpnIssuingService.issueLegalEntityBpns(1).single() taskEntryBpnMapping.addMapping(bpnLReference, bpnL) - val createdLe = createLegalEntity(legalEntityDto, bpnL, legalEntityMetadataMap) + val createdLe = BusinessPartnerBuildService.createLegalEntity(legalEntityDto, bpnL, legalEntityDto.legalName, legalEntityMetadataMap) val address = createLogisticAddress(legalAddress, taskEntryBpnMapping) createdLe.legalAddress = address address.legalEntity = createdLe @@ -358,8 +260,7 @@ class TaskStepBuildService( val updateLe = legalEntityRepository.findByBpn(bpn) if (updateLe != null) { if (legalEntityDto.hasChanged == false) { - updateLegalEntity(updateLe, legalEntityDto, - legalEntityDto.identifiers.map { BusinessPartnerBuildService.toLegalEntityIdentifier(it, legalEntityMetadataMap.idTypes, updateLe) }) + BusinessPartnerBuildService.updateLegalEntity(updateLe, legalEntityDto, legalEntityDto.legalName, legalEntityMetadataMap) val addressMetadataMap = metadataService.getMetadata(listOf(legalAddress)).toMapping() updateLogisticAddress(updateLe.legalAddress, legalAddress, addressMetadataMap) } @@ -390,7 +291,7 @@ class TaskStepBuildService( val upsertSite = if (bpn == null) { val bpnS = bpnIssuingService.issueSiteBpns(1).single() - val createSite = createSite(siteDto, bpnS, legalEntity) + val createSite = BusinessPartnerBuildService.createSite(siteDto, bpnS, legalEntity) taskEntryBpnMapping.addMapping(bpnSReference, bpnS) val address = createLogisticAddress(mainAddress, taskEntryBpnMapping) createSite.mainAddress = address @@ -401,7 +302,7 @@ class TaskStepBuildService( val updateSite = siteRepository.findByBpn(siteDto.bpnSReference?.referenceValue!!) if (updateSite != null) { if (siteDto.hasChanged == false) { - updateSite(updateSite, siteDto) + BusinessPartnerBuildService.updateSite(updateSite, siteDto) val addressMetadataMap = metadataService.getMetadata(listOf(mainAddress)).toMapping() updateLogisticAddress(updateSite.mainAddress, mainAddress, addressMetadataMap) } @@ -420,37 +321,6 @@ class TaskStepBuildService( return upsertSite } - private fun createSite( - siteDto: SiteDto, - bpnS: String, - partner: LegalEntity - ): Site { - - val name = siteDto.name ?: throw BpdmValidationException(CleaningError.SITE_NAME_IS_NULL.message) - - val site = Site( - bpn = bpnS, - name = name, - legalEntity = partner, - ) - - site.states.addAll(siteDto.states - .map { BusinessPartnerBuildService.toSiteState(it, site) }) - - return site - } - - private fun updateSite(site: Site, siteDto: SiteDto) { - - val name = siteDto.name ?: throw BpdmValidationException(CleaningError.SITE_NAME_IS_NULL.message) - - site.name = name - - site.states.clear() - site.states.addAll(siteDto.states - .map { BusinessPartnerBuildService.toSiteState(it, site) }) - } - private fun AddressMetadataDto.toMapping() = BusinessPartnerBuildService.AddressMetadataMapping( idTypes = idTypes.associateBy { it.technicalKey }, diff --git a/bpdm-pool/src/main/kotlin/org/eclipse/tractusx/bpdm/pool/service/TaskStepFetchAndReserveService.kt b/bpdm-pool/src/main/kotlin/org/eclipse/tractusx/bpdm/pool/service/TaskStepFetchAndReserveService.kt index a9a1a47f1..70d0ab762 100644 --- a/bpdm-pool/src/main/kotlin/org/eclipse/tractusx/bpdm/pool/service/TaskStepFetchAndReserveService.kt +++ b/bpdm-pool/src/main/kotlin/org/eclipse/tractusx/bpdm/pool/service/TaskStepFetchAndReserveService.kt @@ -22,6 +22,7 @@ package org.eclipse.tractusx.bpdm.pool.service import mu.KotlinLogging import org.eclipse.tractusx.bpdm.common.dto.IBaseLegalEntityDto import org.eclipse.tractusx.bpdm.common.dto.IBaseLogisticAddressDto +import org.eclipse.tractusx.bpdm.common.dto.RequestWithKey import org.eclipse.tractusx.bpdm.pool.api.model.response.ErrorInfo import org.eclipse.tractusx.bpdm.pool.api.model.response.LegalEntityCreateError import org.eclipse.tractusx.bpdm.pool.exception.BpdmValidationException @@ -105,15 +106,15 @@ class TaskStepFetchAndReserveService( val legalEntityByTask = legalEntitiesToCreateSteps .associateWith { it.businessPartner.legalEntity as IBaseLegalEntityDto } .toMap() - val addressByTask = tasks + val addressByTask = legalEntitiesToCreateSteps .filter { it.businessPartner.legalEntity?.legalAddress != null } .associateWith { it.businessPartner.legalEntity?.legalAddress as IBaseLogisticAddressDto } .toMap() val errorsByRequest = - requestValidationService.validateLegalEntityCreates(legalEntityByTask) { task -> task.businessPartner.legalEntity?.bpnLReference?.referenceValue } + requestValidationService.validateLegalEntityCreates(legalEntityByTask) val errorsByRequestAddress = - requestValidationService.validateLegalEntityCreatesAddresses(addressByTask) { task -> task.businessPartner.legalEntity?.bpnLReference?.referenceValue } + requestValidationService.validateLegalEntityCreatesAddresses(addressByTask) val legalEntityCreateTaskResults = legalEntitiesToCreateSteps .map { taskStep -> @@ -125,8 +126,8 @@ class TaskStepFetchAndReserveService( private fun taskStepResultEntryDto( taskStep: TaskStepReservationEntryDto, - errorsByRequest: Map>>, - errorsByRequestAddress: Map>> + errorsByRequest: Map>>, + errorsByRequestAddress: Map>> ) = if (errorsByRequest.containsKey(taskStep) || errorsByRequestAddress.containsKey(taskStep)) { taskResultsForErrors( taskStep.taskId,