Skip to content

Commit

Permalink
Merge pull request #1142 from eclipse-tractusx/bugfix/legal-name-part…
Browse files Browse the repository at this point in the history
…ner-upload

fix(bpdm-gate): fetched and attached legal name of entity while performing partner upload process.
  • Loading branch information
SujitMBRDI authored Dec 3, 2024
2 parents 3f675b3 + 3345cbc commit a043bdc
Show file tree
Hide file tree
Showing 4 changed files with 144 additions and 9 deletions.
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,13 @@ For changes to the BPDM Helm charts please consult the [changelog](charts/bpdm/C

## [6.3.0] - tbd

### Added


### Changed

- BPDM Gate: Fetched and updated legal name of legal entity from pool while performing partner upload process via CSV([#1141](https://github.com/eclipse-tractusx/bpdm/issues/1141))


## [6.2.0] - 2024-11-28

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,13 @@ package org.eclipse.tractusx.bpdm.gate.service

import com.opencsv.CSVWriter
import mu.KotlinLogging
import org.eclipse.tractusx.bpdm.common.dto.PaginationRequest
import org.eclipse.tractusx.bpdm.gate.api.model.response.BusinessPartnerInputDto
import org.eclipse.tractusx.bpdm.gate.model.PartnerUploadFileHeader
import org.eclipse.tractusx.bpdm.gate.model.PartnerUploadFileRow
import org.eclipse.tractusx.bpdm.gate.util.PartnerFileUtil
import org.eclipse.tractusx.bpdm.pool.api.client.PoolApiClient
import org.eclipse.tractusx.bpdm.pool.api.model.request.LegalEntitySearchRequest
import org.springframework.core.io.ByteArrayResource
import org.springframework.http.ResponseEntity
import org.springframework.stereotype.Service
Expand All @@ -34,15 +37,25 @@ import java.io.OutputStreamWriter

@Service
class PartnerUploadService(
private val businessPartnerService: BusinessPartnerService
private val businessPartnerService: BusinessPartnerService,
private val poolApiClient: PoolApiClient
) {

private val logger = KotlinLogging.logger { }

fun processFile(file: MultipartFile, tenantBpnl: String?): ResponseEntity<Collection<BusinessPartnerInputDto>> {
validateTenantBpnl(tenantBpnl)
val legalName = poolApiClient.legalEntities
.getLegalEntities(
LegalEntitySearchRequest(listOf(tenantBpnl!!)),
PaginationRequest(page = 0, size = 1)
).content.also { entities ->
require(entities.isNotEmpty()) { "No legal entities found for tenantBpnl: $tenantBpnl" }
require(entities.size == 1) { "Multiple legal entities found for tenantBpnl: $tenantBpnl" }
}
.first().legalEntity.legalName
val csvData: List<PartnerUploadFileRow> = PartnerFileUtil.parseCsv(file)
val businessPartnerDtos = PartnerFileUtil.validateAndMapToBusinessPartnerInputRequests(csvData, tenantBpnl)
val businessPartnerDtos = PartnerFileUtil.validateAndMapToBusinessPartnerInputRequests(csvData, tenantBpnl, legalName)
val result = businessPartnerService.upsertBusinessPartnersInput(businessPartnerDtos, tenantBpnl)
return ResponseEntity.ok(result)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ object PartnerFileUtil {
* @return A list of BusinessPartnerInputRequest objects derived from the valid CSV rows.
* @throws BpdmInvalidPartnerUploadException if any validation errors are encountered during processing.
*/
fun validateAndMapToBusinessPartnerInputRequests(csvData: List<PartnerUploadFileRow>, tenantBpnl: String?): List<BusinessPartnerInputRequest> {
fun validateAndMapToBusinessPartnerInputRequests(csvData: List<PartnerUploadFileRow>, tenantBpnl: String?, legalName: String): List<BusinessPartnerInputRequest> {
val formatter = DateTimeFormatter.ISO_DATE_TIME
val validator: Validator = Validation.buildDefaultValidatorFactory().validator
val errors = mutableListOf<String>()
Expand All @@ -85,8 +85,10 @@ object PartnerFileUtil {
states = emptyList(),
roles = emptyList(),
isOwnCompanyData = true,
// Legal entity's business partner number is nothing but tenant's partner number who is performing business partner upload action
legalEntity = LegalEntityRepresentationInputDto(legalEntityBpn = tenantBpnl?.takeIf { it.isNotEmpty() }),
legalEntity = LegalEntityRepresentationInputDto(
legalEntityBpn = tenantBpnl?.takeIf { it.isNotEmpty() },
legalName = legalName
),
site = row.toSiteRepresentationInputDto(formatter, errors, index, row.externalId.orEmpty()),
address = row.toAddressRepresentationInputDto(formatter, errors, index, row.externalId.orEmpty())
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,23 @@

package org.eclipse.tractusx.bpdm.gate.controller

import com.fasterxml.jackson.databind.ObjectMapper
import com.github.tomakehurst.wiremock.client.WireMock
import com.github.tomakehurst.wiremock.client.WireMock.okJson
import com.github.tomakehurst.wiremock.core.WireMockConfiguration
import com.github.tomakehurst.wiremock.junit5.WireMockExtension
import com.neovisionaries.i18n.CountryCode
import org.eclipse.tractusx.bpdm.common.dto.PageDto
import org.eclipse.tractusx.bpdm.common.dto.TypeKeyNameVerboseDto
import org.eclipse.tractusx.bpdm.gate.api.client.GateClient
import org.eclipse.tractusx.bpdm.gate.api.model.request.BusinessPartnerInputRequest
import org.eclipse.tractusx.bpdm.gate.api.model.response.LegalEntityRepresentationInputDto
import org.eclipse.tractusx.bpdm.gate.util.MockAndAssertUtils
import org.eclipse.tractusx.bpdm.pool.api.model.ConfidenceCriteriaDto
import org.eclipse.tractusx.bpdm.pool.api.model.LegalEntityVerboseDto
import org.eclipse.tractusx.bpdm.pool.api.model.LogisticAddressVerboseDto
import org.eclipse.tractusx.bpdm.pool.api.model.PhysicalPostalAddressVerboseDto
import org.eclipse.tractusx.bpdm.pool.api.model.response.LegalEntityWithLegalAddressVerboseDto
import org.eclipse.tractusx.bpdm.test.containers.KeyCloakInitializer
import org.eclipse.tractusx.bpdm.test.containers.PostgreSQLContextInitializer
import org.eclipse.tractusx.bpdm.test.containers.SelfClientInitializer
Expand All @@ -32,15 +45,20 @@ import org.junit.jupiter.api.Assertions.assertEquals
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.assertThrows
import org.junit.jupiter.api.extension.RegisterExtension
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.test.context.SpringBootTest
import org.springframework.http.HttpStatus
import org.springframework.mock.web.MockMultipartFile
import org.springframework.test.context.ActiveProfiles
import org.springframework.test.context.ContextConfiguration
import org.springframework.test.context.DynamicPropertyRegistry
import org.springframework.test.context.DynamicPropertySource
import org.springframework.web.reactive.function.client.WebClientResponseException
import java.nio.file.Files
import java.nio.file.Paths
import java.time.Instant
import java.time.LocalDateTime

@SpringBootTest(
webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT,
Expand All @@ -56,12 +74,32 @@ import java.nio.file.Paths
class PartnerUploadControllerIT @Autowired constructor(
val testHelpers: DbTestHelpers,
val gateClient: GateClient,
val jacksonObjectMapper: ObjectMapper,
val mockAndAssertUtils: MockAndAssertUtils
) {

companion object {

const val TENANT_BPNL = KeyCloakInitializer.TENANT_BPNL
const val MOCKED_LEGAL_NAME = "Mocked Legal Name"

@JvmField
@RegisterExtension
val poolWireMockApi: WireMockExtension = WireMockExtension.newInstance().options(WireMockConfiguration.wireMockConfig().dynamicPort()).build()

@JvmStatic
@DynamicPropertySource
fun properties(registry: DynamicPropertyRegistry) {
registry.add("bpdm.client.pool.base-url") { poolWireMockApi.baseUrl() }
}

}

@BeforeEach
fun beforeEach() {
testHelpers.truncateDbTables()
poolWireMockApi.resetAll()
poolMockGetLegalEntitiesApi(TENANT_BPNL, MOCKED_LEGAL_NAME)
}

@Test
Expand All @@ -88,8 +126,8 @@ class PartnerUploadControllerIT @Autowired constructor(
// Only Site and Address expected to be updated from upload partner process.
val expectedSiteAndAddressPartner = BusinessPartnerVerboseValues.bpUploadRequestFull.copy(
legalEntity = LegalEntityRepresentationInputDto(
legalEntityBpn = KeyCloakInitializer.TENANT_BPNL,
legalName = null,
legalEntityBpn = TENANT_BPNL,
legalName = MOCKED_LEGAL_NAME,
shortName = null,
legalForm = null,
states = emptyList()
Expand Down Expand Up @@ -132,8 +170,8 @@ class PartnerUploadControllerIT @Autowired constructor(

val expectedSiteAndAddressPartner = BusinessPartnerVerboseValues.bpUploadRequestFull.copy(
legalEntity = LegalEntityRepresentationInputDto(
legalEntityBpn = KeyCloakInitializer.TENANT_BPNL,
legalName = null,
legalEntityBpn = TENANT_BPNL,
legalName = MOCKED_LEGAL_NAME,
shortName = null,
legalForm = null,
states = emptyList()
Expand All @@ -156,6 +194,81 @@ class PartnerUploadControllerIT @Autowired constructor(
this.mockAndAssertUtils.assertUpsertResponsesMatchRequests(searchResponsePage, expectedResponse)
}

fun poolMockGetLegalEntitiesApi(tenantBpnl: String, legalName: String) {
val legalEntity1 = LegalEntityVerboseDto(
bpnl = tenantBpnl,
legalName = legalName,
legalShortName = null,
legalFormVerbose = null,
identifiers = emptyList(),
states = emptyList(),
relations = emptyList(),
currentness = Instant.now(),
confidenceCriteria = ConfidenceCriteriaDto(
sharedByOwner = true,
checkedByExternalDataSource = true,
numberOfSharingMembers = 0,
lastConfidenceCheckAt = LocalDateTime.of(2023, 10, 10, 10, 10, 10),
nextConfidenceCheckAt = LocalDateTime.of(2024, 10, 10, 10, 10, 10),
confidenceLevel = 0
),
isCatenaXMemberData = false,
createdAt = Instant.now(),
updatedAt = Instant.now()
)

val legalAddress1 = LogisticAddressVerboseDto(
bpna = "BPNA00000000009W",
physicalPostalAddress = PhysicalPostalAddressVerboseDto(
geographicCoordinates = null,
countryVerbose = TypeKeyNameVerboseDto(CountryCode.DE, CountryCode.DE.getName()),
postalCode = null,
city = "Stuttgart",
administrativeAreaLevel1Verbose = null,
administrativeAreaLevel2 = null,
administrativeAreaLevel3 = null,
district = null,
companyPostalCode = null,
industrialZone = null,
building = null,
floor = null,
door = null,
street = null,
taxJurisdictionCode = null
),
bpnLegalEntity = null,
bpnSite = null,
confidenceCriteria = ConfidenceCriteriaDto(
sharedByOwner = true,
checkedByExternalDataSource = true,
numberOfSharingMembers = 0,
lastConfidenceCheckAt = LocalDateTime.of(2023, 10, 10, 10, 10, 10),
nextConfidenceCheckAt = LocalDateTime.of(2024, 10, 10, 10, 10, 10),
confidenceLevel = 0
),
isCatenaXMemberData = false,
createdAt = Instant.now(),
updatedAt = Instant.now()
)

val responseBody = PageDto(
1, 1, 0, 1,
listOf(
LegalEntityWithLegalAddressVerboseDto(legalEntity = legalEntity1, legalAddress = legalAddress1)
)
)

poolWireMockApi.stubFor(
WireMock.get(WireMock.urlPathEqualTo("/v6/legal-entities"))
.withQueryParam("bpnLs", WireMock.equalTo(tenantBpnl))
.withQueryParam("page", WireMock.equalTo("0"))
.withQueryParam("size", WireMock.equalTo("1"))
.willReturn(
okJson(jacksonObjectMapper.writeValueAsString(responseBody))
)
)
}


private fun testFileUpload(filePath: String, expectedStatus: HttpStatus) {
val bytes = Files.readAllBytes(Paths.get(filePath))
Expand Down

0 comments on commit a043bdc

Please sign in to comment.