Skip to content

Commit

Permalink
feat(bpdm): post endpoint to upload business partner data using csv file
Browse files Browse the repository at this point in the history
  • Loading branch information
SujitMBRDI committed Jun 12, 2024
1 parent 1f2f9e0 commit afc50ea
Show file tree
Hide file tree
Showing 18 changed files with 889 additions and 1 deletion.
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
/*******************************************************************************
* Copyright (c) 2021,2024 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

import io.swagger.v3.oas.annotations.Operation
import io.swagger.v3.oas.annotations.media.Content
import io.swagger.v3.oas.annotations.media.Schema
import io.swagger.v3.oas.annotations.responses.ApiResponse
import io.swagger.v3.oas.annotations.responses.ApiResponses
import org.eclipse.tractusx.bpdm.gate.api.GateBusinessPartnerApi.Companion.BUSINESS_PARTNER_PATH
import org.eclipse.tractusx.bpdm.gate.api.model.response.BusinessPartnerInputDto
import org.eclipse.tractusx.bpdm.gate.api.model.response.PartnerUploadErrorResponse
import org.springframework.http.MediaType
import org.springframework.http.ResponseEntity
import org.springframework.web.bind.annotation.PostMapping
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.RequestPart
import org.springframework.web.multipart.MultipartFile

@RequestMapping(BUSINESS_PARTNER_PATH, produces = [MediaType.APPLICATION_JSON_VALUE, MediaType.MULTIPART_FORM_DATA_VALUE])
interface GatePartnerUploadApi {

companion object{
const val BUSINESS_PARTNER_PATH = ApiCommons.BASE_PATH
}

@Operation(
summary = "Create or update business partners from uploaded CSV file",
description = "Create or update generic business partners. " +
"Updates instead of creating a new business partner if an already existing external ID is used. " +
"The same external ID may not occur more than once in a single request. " +
"For file upload request, the maximum number of business partners in file limited to \${bpdm.api.upsert-limit} entries.",
)
@ApiResponses(
value = [
ApiResponse(responseCode = "200", description = "Business partners were successfully updated or created"),
ApiResponse(responseCode = "400", description = "On malformed Business partner upload request",
content = [Content(
mediaType = "application/json",
schema = Schema(implementation = PartnerUploadErrorResponse::class)
)]),
]
)
@PostMapping("/input/partner-upload-process/upload-partner-csv", consumes = ["multipart/form-data"])
fun uploadPartnerCsvFile(
@RequestPart("file") file: MultipartFile
): ResponseEntity<Collection<BusinessPartnerInputDto>>

}
Original file line number Diff line number Diff line change
Expand Up @@ -30,4 +30,6 @@ interface GateClient {
val sharingState: SharingStateApiClient

val stats: StatsApiClient

val partnerUpload: PartnerUploadApiClient
}
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ class GateClientImpl(

override val stats by lazy { createClient<StatsApiClient>() }

override val partnerUpload by lazy { createClient<PartnerUploadApiClient>() }

private inline fun <reified T> createClient() =
httpServiceProxyFactory.createClient(T::class.java)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/*******************************************************************************
* Copyright (c) 2021,2024 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.client

import org.eclipse.tractusx.bpdm.gate.api.GatePartnerUploadApi
import org.eclipse.tractusx.bpdm.gate.api.model.response.BusinessPartnerInputDto
import org.springframework.http.MediaType
import org.springframework.http.ResponseEntity
import org.springframework.web.bind.annotation.RequestPart
import org.springframework.web.multipart.MultipartFile
import org.springframework.web.service.annotation.HttpExchange
import org.springframework.web.service.annotation.PostExchange

@HttpExchange(GatePartnerUploadApi.BUSINESS_PARTNER_PATH)
interface PartnerUploadApiClient : GatePartnerUploadApi {

@PostExchange(
url = "/input/partner-upload-process/upload-partner-csv",
contentType = MediaType.MULTIPART_FORM_DATA_VALUE,
accept = ["application/json"]
)
override fun uploadPartnerCsvFile(
@RequestPart("file") file: MultipartFile
): ResponseEntity<Collection<BusinessPartnerInputDto>>

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/*******************************************************************************
* Copyright (c) 2021,2024 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.response

import io.swagger.v3.oas.annotations.media.Schema
import org.springframework.http.HttpStatus
import java.time.Instant

@Schema(description = "Error response for invalid partner upload")
class PartnerUploadErrorResponse(
@Schema(description = "Timestamp of the error occurrence")
val timestamp: Instant,
@Schema(description = "HTTP status of the error response")
val status: HttpStatus,
@Schema(description = "List of error messages")
val error: List<String>,
@Schema(description = "Request path where the error occurred")
val path: String
)
5 changes: 5 additions & 0 deletions bpdm-gate/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,11 @@
<groupId>org.eclipse.tractusx</groupId>
<artifactId>bpdm-orchestrator-api</artifactId>
</dependency>
<dependency>
<groupId>com.opencsv</groupId>
<artifactId>opencsv</artifactId>
<version>5.9</version>
</dependency>
</dependencies>

<build>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
/*******************************************************************************
* Copyright (c) 2021,2024 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.controller

import org.eclipse.tractusx.bpdm.gate.api.GatePartnerUploadApi
import org.eclipse.tractusx.bpdm.gate.api.model.response.BusinessPartnerInputDto
import org.eclipse.tractusx.bpdm.gate.config.ApiConfigProperties
import org.eclipse.tractusx.bpdm.gate.config.PermissionConfigProperties
import org.eclipse.tractusx.bpdm.gate.service.BusinessPartnerService
import org.eclipse.tractusx.bpdm.gate.service.PartnerUploadService
import org.eclipse.tractusx.bpdm.gate.util.getCurrentUserBpn
import org.springframework.http.HttpStatus
import org.springframework.http.ResponseEntity
import org.springframework.security.access.prepost.PreAuthorize
import org.springframework.web.bind.annotation.RestController
import org.springframework.web.multipart.MultipartFile

@RestController
class PartnerUploadController(
val businessPartnerService: BusinessPartnerService,
val apiConfigProperties: ApiConfigProperties,
val partnerUploadService: PartnerUploadService
) : GatePartnerUploadApi {

@PreAuthorize("hasAuthority(${PermissionConfigProperties.WRITE_INPUT_PARTNER})")
override fun uploadPartnerCsvFile(
file: MultipartFile
): ResponseEntity<Collection<BusinessPartnerInputDto>> {
return when {
file.isEmpty -> ResponseEntity(HttpStatus.BAD_REQUEST)
!file.contentType.equals("text/csv", ignoreCase = true) -> ResponseEntity(HttpStatus.BAD_REQUEST)
else -> partnerUploadService.processFile(file, getCurrentUserBpn())
}
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/*******************************************************************************
* Copyright (c) 2021,2024 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.exception

class BpdmInvalidPartnerUploadException(
val errors: List<String>
) : RuntimeException()
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,25 @@
package org.eclipse.tractusx.bpdm.gate.exception

import org.eclipse.tractusx.bpdm.common.exception.BpdmExceptionHandler
import org.eclipse.tractusx.bpdm.gate.api.model.response.PartnerUploadErrorResponse
import org.springframework.http.HttpStatus
import org.springframework.http.ResponseEntity
import org.springframework.web.bind.annotation.ControllerAdvice
import org.springframework.web.bind.annotation.ExceptionHandler
import org.springframework.web.context.request.WebRequest
import java.time.Instant

@ControllerAdvice
class GateExceptionHandler : BpdmExceptionHandler()
class GateExceptionHandler : BpdmExceptionHandler() {

@ExceptionHandler(BpdmInvalidPartnerUploadException::class)
fun handleInvalidPartnerUploadException(ex:BpdmInvalidPartnerUploadException, request: WebRequest): ResponseEntity<PartnerUploadErrorResponse> {
val errorResponse = PartnerUploadErrorResponse(
timestamp = Instant.now(),
status = HttpStatus.BAD_REQUEST,
error = ex.errors,
path = request.getDescription(false)
)
return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(errorResponse)
}
}
Loading

0 comments on commit afc50ea

Please sign in to comment.