Skip to content

Commit

Permalink
Merge branch 'main' into feat/demand-and-capacity-notification-edc-in…
Browse files Browse the repository at this point in the history
…tegration
  • Loading branch information
ReneSchroederLJ committed Jun 20, 2024
2 parents a189058 + 8263810 commit 690ee98
Show file tree
Hide file tree
Showing 17 changed files with 536 additions and 217 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,7 @@ private void setupCustomerRole() throws JsonProcessingException {
.directionCharacteristic(DirectionCharacteristic.INBOUND)
.requestType("ItemStock")
.sammVersion("2.0")
.responseCode(201)
.build();
mockRequest = erpAdapterRequestService.create(mockRequest);
log.info("Created mocked ErpAdapterRequest: \n{}", mockRequest);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -335,12 +335,6 @@ public JsonNode buildProxyPullRequestBody(Partner partner, String contractID, St
dataDestination.put("type", "HttpProxy");
body.set("dataDestination", dataDestination);

// This private property is not evaluated in EDC 0.7.0 anymore due to data plane signalling
// EDRs are taken manually
var privateProperties = MAPPER.createObjectNode();
privateProperties.put("receiverHttpEndpoint", variablesService.getEdrEndpoint());
body.set("privateProperties", privateProperties);

log.debug("Built Proxy Pull Request:\n{}", body.toPrettyString());
return body;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;


@Getter
@Service
/**
Expand Down Expand Up @@ -69,18 +68,13 @@ public String getContextPath() {
return contextPath.replace("/", "") + "/";
}

@Value("${puris.baseurl}" + "catena/edrendpoint")
/**
* The edrEndpoint to be used during consumer pull asset transfers.
*/
private String edrEndpoint;

@Value("${puris.baseurl}" + "catena/item-stock/request")
/**
* The url under which this application's request endpoint can
* The url under which this application's item stock request endpoint can
* be reached by external machines.
*/
private String itemStockSubmodelEndpoint;
public String getItemStockSubmodelEndpoint() {
return getPurisBaseUrl() + getContextPath() + "item-stock/request";
}

@Value("${puris.itemstocksubmodel.apiassetid}")
/**
Expand All @@ -89,12 +83,13 @@ public String getContextPath() {
*/
private String itemStockSubmodelAssetId;

@Value("${puris.baseurl}" + "catena/planned-production/request")
/**
* The url under which this application's request endpoint can
* The url under which this application's planned production request endpoint can
* be reached by external machines.
*/
private String productionSubmodelEndpoint;
public String getProductionSubmodelEndpoint() {
return getPurisBaseUrl() + getContextPath() + "planned-production/request";
}

@Value("${puris.productionsubmodel.apiassetid}")
/**
Expand All @@ -103,12 +98,13 @@ public String getContextPath() {
*/
private String productionSubmodelAssetId;

@Value("${puris.baseurl}" + "catena/material-demand/request")
/**
* The url under which this application's request endpoint can
* The url under which this application's material demand request endpoint can
* be reached by external machines.
*/
private String demandSubmodelEndpoint;
public String getDemandSubmodelEndpoint() {
return getPurisBaseUrl() + getContextPath() + "material-demand/request";
}

@Value("${puris.demandsubmodel.apiassetid}")
/**
Expand All @@ -117,12 +113,13 @@ public String getContextPath() {
*/
private String demandSubmodelAssetId;

@Value("${puris.baseurl}" + "catena/delivery-information/request")
/**
* The url under which this application's request endpoint can
* The url under which this application's delivery information request endpoint can
* be reached by external machines.
*/
private String deliverySubmodelEndpoint;
public String getDeliverySubmodelEndpoint() {
return getPurisBaseUrl() + getContextPath() + "delivery-information/request";
}

@Value("${puris.deliverysubmodel.apiassetid}")
/**
Expand Down Expand Up @@ -182,8 +179,13 @@ public String getNotificationEndpoint() {
*/
private String dtrUrl;

@Value("${puris.baseurl}" + "catena/parttypeinformation")
private String parttypeInformationServerendpoint;
/**
* The url under which this application's part type request endpoint can
* be reached by external machines.
*/
public String getParttypeInformationServerendpoint() {
return getPurisBaseUrl() + getContextPath() + "parttypeinformation";
}

@Value("${puris.generatematerialcatenaxid}")
/**
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package org.eclipse.tractusx.puris.backend.erpadapter;

import lombok.Getter;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;

@Configuration
@Getter
public class ErpAdapterConfiguration {

/**
* Toggles usage of the ERP adapter
*/
@Value("${puris.erpadapter.enabled}")
private boolean erpAdapterEnabled;

/**
* The URL of the ERP adapter
*/
@Value("${puris.erpadapter.url}")
private String erpAdapterUrl;

/**
* The URL under which we expect responses from
* the ERP adapter
*/
@Value("${puris.baseurl}" + "${server.servlet.context-path}" + "/erp-adapter")
private String erpResponseUrl;

/**
* The auth-key used when accessing the ERP adapter's
* request interface
*/
@Value("${puris.erpadapter.authkey}")
private String erpAdapterAuthKey;

/**
* The auth-secret used when accessing the ERP adapter's
* request interface
*/
@Value("${puris.erpadapter.authsecret}")
private String erpAdapterAuthSecret;
}
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,8 @@ public class ErpAdapterRequest {
@NotNull
private Date requestDate;

private Integer responseCode;

private Date responseReceivedDate;

@Pattern(regexp = PatternStore.NON_EMPTY_NON_VERTICAL_WHITESPACE_STRING)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
/*
* Copyright (c) 2024 Volkswagen AG
* Copyright (c) 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.puris.backend.erpadapter.logic.service;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import okhttp3.*;
import org.eclipse.tractusx.puris.backend.erpadapter.ErpAdapterConfiguration;
import org.eclipse.tractusx.puris.backend.erpadapter.domain.model.ErpAdapterRequest;
import org.springframework.stereotype.Service;

import java.io.IOException;

@Service
@Slf4j
@RequiredArgsConstructor
public class ErpAdapterRequestClient {

private final OkHttpClient client = new OkHttpClient();

private final ObjectMapper mapper = new ObjectMapper();

private final ErpAdapterConfiguration erpAdapterConfiguration;

public Integer sendRequest(ErpAdapterRequest erpAdapterRequest){
HttpUrl.Builder urlBuilder = HttpUrl.parse(erpAdapterConfiguration.getErpAdapterUrl()).newBuilder();
urlBuilder.addQueryParameter("bpnl", erpAdapterRequest.getPartnerBpnl());
urlBuilder.addQueryParameter("request-type", erpAdapterRequest.getRequestType());
urlBuilder.addQueryParameter("request-id", erpAdapterRequest.getId().toString());
urlBuilder.addQueryParameter("samm-version", erpAdapterRequest.getSammVersion());
urlBuilder.addQueryParameter("request-timestamp", String.valueOf(erpAdapterRequest.getRequestDate().getTime()));

ObjectNode requestBody = mapper.createObjectNode();

requestBody.put("material", erpAdapterRequest.getOwnMaterialNumber());
requestBody.put("direction", erpAdapterRequest.getDirectionCharacteristic().toString());
requestBody.put("responseUrl", erpAdapterConfiguration.getErpResponseUrl());

RequestBody body = RequestBody.create(requestBody.toString(), MediaType.parse("application/json"));

Request request = new Request.Builder()
.post(body)
.url(urlBuilder.build())
.header(erpAdapterConfiguration.getErpAdapterAuthKey(), erpAdapterConfiguration.getErpAdapterAuthSecret())
.header("Content-Type", "application/json")
.build();
try (var response = client.newCall(request).execute()) {
return response.code();
} catch (IOException e) {
log.error("Error while sending ErpAdapterRequest", e);
return null;
}

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,26 +20,49 @@

package org.eclipse.tractusx.puris.backend.erpadapter.logic.service;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.eclipse.tractusx.puris.backend.erpadapter.domain.model.ErpAdapterRequest;
import org.eclipse.tractusx.puris.backend.erpadapter.domain.repository.ErpAdapterRequestRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.UUID;

@Service
@Slf4j
@RequiredArgsConstructor
public class ErpAdapterRequestService {

@Autowired
private ErpAdapterRequestRepository repository;
private final ErpAdapterRequestRepository repository;

private final ErpAdapterRequestClient erpAdapterRequestClient;

public ErpAdapterRequest create(ErpAdapterRequest erpAdapterRequest) {
if (erpAdapterRequest.getId() != null && repository.existsById(erpAdapterRequest.getId())) {
log.error("ErpAdapterRequest with id {} already exists", erpAdapterRequest.getId());
return null;
}
return repository.save(erpAdapterRequest);
}

public void createAndSend(ErpAdapterRequest erpAdapterRequest) {
erpAdapterRequest = create(erpAdapterRequest);
if (erpAdapterRequest != null) {
Integer responseCode = erpAdapterRequestClient.sendRequest(erpAdapterRequest);
if (responseCode != null) {
if (responseCode >= 200 && responseCode < 400) {
log.info("Successfully sent request to ERP Adapter, got status code {} for request:\n{}", responseCode, erpAdapterRequest);
} else {
log.warn("Received status code {} from ERP Adapter for request:\n{}", responseCode, erpAdapterRequest);
}
erpAdapterRequest.setResponseCode(responseCode);
update(erpAdapterRequest);
} else {
log.error("Failed to send request to ERP Adapter:\n{}", erpAdapterRequest);
}
}
}

public ErpAdapterRequest get(UUID id) {
// TODO: Remove when mock is removed
return repository.findById(id).orElse(repository.findAll().getFirst());
Expand All @@ -50,6 +73,7 @@ public ErpAdapterRequest update(ErpAdapterRequest erpAdapterRequest) {
if (repository.existsById(erpAdapterRequest.getId())) {
return repository.save(erpAdapterRequest);
}
log.error("ErpAdapterRequest with id {} did not exist, could not update entity", erpAdapterRequest.getId());
return null;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,10 @@ public int receiveItemStockUpdate(ErpAdapterController.Dto dto) {
// log.error("Received duplicate response for messageId {}", request.getId());
// return 409;
// }
if (request.getResponseCode() == null || request.getResponseCode() < 200 || request.getResponseCode() >= 400) {
log.error("Unexpected response, erp adapter had not confirmed request");
return 404;
}
if (!request.getPartnerBpnl().equals(dto.partnerBpnl())) {
log.error("BPNL mismatch! request BPNL: {}, message BPNL: {}",
request.getPartnerBpnl(), dto.partnerBpnl());
Expand Down
4 changes: 4 additions & 0 deletions backend/src/main/resources/application.properties
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@ puris.dtr.idp.edc-client.id=${PURIS_DTR_IDP_EDC-CLIENT_ID:FOSS-DTR-CLIENT}
puris.dtr.idp.edc-client.secret.alias=${PURIS_DTR_IDP_EDC-CLIENT_SECRET_ALIAS}
puris.dtr.idp.puris-client.id=${PURIS_DTR_IDP_PURIS-CLIENT_ID:FOSS-DTR-CLIENT}
puris.dtr.idp.puris-client.secret=${PURIS_DTR_IDP_PURIS-CLIENT_SECRET}
puris.erpadapter.enabled=${PURIS_ERPADAPTER_ENABLED:false}
puris.erpadapter.url=${PURIS_ERPADAPTER_URL:http://my-erpadapter:8080}
puris.erpadapter.authkey=${PURIS_ERPADAPTER_AUTHKEY:x-api-key}
puris.erpadapter.authsecret=${PURIS_ERPADAPTER_AUTHSECRET:erp-password}
# Flag that decides whether the auto-generation feature of the puris backend is enabled.
# Since all Material entities are required to have a CatenaX-Id, you must enter any pre-existing CatenaX-Id
# via the materials-API of the backend, when you are inserting a new Material entity to the backend's
Expand Down
Loading

0 comments on commit 690ee98

Please sign in to comment.