mp
}
/**
- * Call this method when a new Material with a product flag was created in your MaterialService - or if a product
- * flag was later added to an existing Material.
+ * Call this method when you need to register a product at the DTR for which there was no product AAS registered
+ * previously.
*
* A new AAS will be registered for this Material at your dDTR.
*
* @param material The Material
+ * @param mprs The list of all MaterialProductRelations that exist with customers of the given Material
* @return The HTTP response code from the DTR, or null if none was received
*/
- public Integer registerProductAtDtr(Material material) {
+ public Integer registerProductAtDtr(Material material, List mprs) {
String twinId = digitalTwinMappingService.get(material).getProductTwinId();
- var body = dtrRequestBodyBuilder.createProductRegistrationRequestBody(material, twinId, List.of());
+ var body = dtrRequestBodyBuilder.createProductRegistrationRequestBody(material, twinId, mprs);
try (var response = sendDtrPostRequest(body, List.of("api", "v3", "shell-descriptors"))) {
return response.code();
} catch (Exception e) {
diff --git a/backend/src/main/java/org/eclipse/tractusx/puris/backend/common/edc/logic/service/EdcAdapterService.java b/backend/src/main/java/org/eclipse/tractusx/puris/backend/common/edc/logic/service/EdcAdapterService.java
index d80ff8d5..e3d278fe 100644
--- a/backend/src/main/java/org/eclipse/tractusx/puris/backend/common/edc/logic/service/EdcAdapterService.java
+++ b/backend/src/main/java/org/eclipse/tractusx/puris/backend/common/edc/logic/service/EdcAdapterService.java
@@ -22,7 +22,6 @@
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
-import com.fasterxml.jackson.databind.node.ObjectNode;
import lombok.extern.slf4j.Slf4j;
import okhttp3.*;
import org.eclipse.tractusx.puris.backend.common.edc.domain.model.SubmodelType;
@@ -178,7 +177,7 @@ public boolean registerAssetsInitially() {
* Utility method to register policy- and contract-definitions for both the
* REQUEST and the RESPONSE-Api specifically for the given partner.
*
- * @param partner the partner
+ * @param partner The partner
* @return true, if all registrations ran successfully
*/
public boolean createPolicyAndContractDefForPartner(Partner partner) {
@@ -227,7 +226,7 @@ private boolean createDtrContractDefinitionForPartner(Partner partner) {
* 1. The BPNL of the requesting connector is equal to the BPNL of the partner
* 2. There's a CX membership credential present
*
- * @param partner the partner to create the policy for
+ * @param partner The partner to create the policy for
* @return true, if registration ran successfully
*/
private boolean createBpnlAndMembershipPolicyDefinitionForPartner(Partner partner) {
@@ -475,8 +474,8 @@ public Response getAllTransfers() throws IOException {
* Sends a request to the own control plane in order to receive
* the contract agreement with the given contractAgreementId
*
- * @param contractAgreementId the contractAgreement's Id
- * @return the contractAgreement
+ * @param contractAgreementId The contractAgreement's Id
+ * @return The contractAgreement
* @throws IOException If the connection to your control plane fails
*/
public String getContractAgreement(String contractAgreementId) throws IOException {
@@ -558,7 +557,7 @@ private JsonNode getSubmodelFromPartner(MaterialPartnerRelation mpr, SubmodelTyp
}
}
if (!partner.getEdcUrl().equals(partnerDspUrl)) {
- log.warn("Divering Edc Urls for Partner: " + partner.getBpnl() + " and type " + type);
+ log.warn("Diverging Edc Urls for Partner: " + partner.getBpnl() + " and type " + type);
log.warn("General Partner EdcUrl: " + partner.getEdcUrl());
log.warn("URL from AAS: " + partnerDspUrl);
}
@@ -568,13 +567,6 @@ private JsonNode getSubmodelFromPartner(MaterialPartnerRelation mpr, SubmodelTyp
String transferId = transferResp.get("@id").asText();
// try proxy pull and terminate request
try {
- for (int i = 0; i < 100; i++) {
- Thread.sleep(100);
- transferResp = getTransferState(transferId);
- if ("STARTED".equals(transferResp.get("state").asText())) {
- break;
- }
- }
EdrDto edrDto = getAndAwaitEdrDto(transferId);
log.info("Received EDR data for " + assetId + " with " + partner.getEdcUrl());
if (edrDto == null) {
@@ -610,17 +602,24 @@ private JsonNode getSubmodelFromPartner(MaterialPartnerRelation mpr, SubmodelTyp
}
/**
- * get the EDR via edr api and retry multiple times in case the EDR has not yet been available
+ * Get the EDR via edr api and retry multiple times in case the EDR has not yet been available
*
* @param transferProcessId to get the EDR for, not null
* @return edr received, or null if not yet available
* @throws InterruptedException if thread was not able to sleep
*/
- private @Nullable EdrDto getAndAwaitEdrDto(String transferProcessId) throws InterruptedException {
+ private @Nullable EdrDto getAndAwaitEdrDto(String transferProcessId) throws InterruptedException, IOException {
+ for (int i = 0; i < 100; i++) {
+ Thread.sleep(100);
+ JsonNode transferResp = getTransferState(transferProcessId);
+ if ("STARTED".equals(transferResp.get("state").asText())) {
+ break;
+ }
+ }
EdrDto edrDto = null;
// retry, if Data Space Protocol / Data Plane Provisioning communication needs time to prepare
for (int i = 0; i < 100; i++) {
- edrDto = getEdrForTransferProcessId(transferProcessId);
+ edrDto = getEdrForTransferProcessId(transferProcessId, 2);
if (edrDto != null) {
break;
}
@@ -747,7 +746,7 @@ private SubmodelData fetchSubmodelData(MaterialPartnerRelation mpr, String seman
}
/**
- * quries the dtr of a pratner for the given mpr / material and returns submodel descriptors
+ * Queries the dtr of a partner for the given mpr / material and returns submodel descriptors
*
* Method assumes that the query at dtr only finds one shell (else take first entry)
*
@@ -762,7 +761,11 @@ private JsonNode getAasSubmodelDescriptors(String manufacturerPartId, String man
log.error("AasSubmodelDescriptors Request failed for " + manufacturerPartId + " and " + manufacturerId);
return null;
}
- boolean failed = true;
+
+ // A criticalFailure indicates that the connection to the partner's DTR could not be established at all
+ // or delivers a completely unexpected response. This is assumed to be true at first, and will be set to false
+ // if a response was received that contains the expected answer or at least an empty result.
+ boolean criticalFailure = true;
Partner partner = mpr.getPartner();
try {
var dtrContractData = edcContractMappingService.getDtrAssetAndContractId(partner);
@@ -779,13 +782,6 @@ private JsonNode getAasSubmodelDescriptors(String manufacturerPartId, String man
var transferResp = initiateProxyPullTransfer(partner, contractId, assetId);
String transferId = transferResp.get("@id").asText();
try {
- for (int i = 0; i < 100; i++) {
- Thread.sleep(100);
- transferResp = getTransferState(transferId);
- if ("STARTED".equals(transferResp.get("state").asText())) {
- break;
- }
- }
EdrDto edrDto = getAndAwaitEdrDto(transferId);
if (edrDto == null) {
log.error("Failed to obtain EDR data for " + assetId + " with " + partner.getEdcUrl());
@@ -834,7 +830,7 @@ private JsonNode getAasSubmodelDescriptors(String manufacturerPartId, String man
var aasJson = objectMapper.readTree(body2String);
var submodelDescriptors = aasJson.get("submodelDescriptors");
if (submodelDescriptors != null) {
- failed = false;
+ criticalFailure = false;
return submodelDescriptors;
} else {
log.warn("No SubmodelDescriptors found in DTR shell-descriptors response:\n" + aasJson.toPrettyString());
@@ -844,6 +840,7 @@ private JsonNode getAasSubmodelDescriptors(String manufacturerPartId, String man
if (resultArray != null) {
if (resultArray.isArray() && resultArray.isEmpty()) {
log.warn("Empty Result array received");
+ criticalFailure = false;
} else {
log.warn("Unexpected Response for DTR lookup with query " + query + "\n" + resultArray.toPrettyString());
}
@@ -862,7 +859,7 @@ private JsonNode getAasSubmodelDescriptors(String manufacturerPartId, String man
log.error("Error in AasSubmodelDescriptor Request for " + mpr + " and manufacturerPartId " + manufacturerPartId, e);
return getAasSubmodelDescriptors(manufacturerPartId, manufacturerId, mpr, --retries);
} finally {
- if (failed) {
+ if (criticalFailure) {
log.warn("Invalidating DTR contract data");
edcContractMappingService.putDtrContractData(partner, null, null);
}
@@ -879,27 +876,38 @@ private JsonNode getAasSubmodelDescriptors(String manufacturerPartId, String man
* @param transferProcessId to get the EDR for
* @return unpersisted EdrDto.
*/
- private EdrDto getEdrForTransferProcessId(String transferProcessId) {
-
+ private EdrDto getEdrForTransferProcessId(String transferProcessId, int retries) {
+ if (retries < 0) return null;
+ boolean failed = true;
try (Response response = sendGetRequest(
List.of("v2", "edrs", transferProcessId, "dataaddress"),
Map.of("auto_refresh", "true"))
) {
- ObjectNode responseObject = (ObjectNode) objectMapper.readTree(response.body().string());
-
- String dataPlaneEndpoint = responseObject.get("endpoint").asText();
- String authToken = responseObject.get("authorization").asText();
-
- EdrDto edr = new EdrDto("Authorization", authToken, dataPlaneEndpoint);
- log.debug("Requested EDR successfully: {}", edr);
-
- return edr;
-
- } catch (IOException e) {
+ if (response.isSuccessful() && response.body() != null) {
+ JsonNode responseObject = objectMapper.readTree(response.body().string());
+
+ String dataPlaneEndpoint = responseObject.get("endpoint").asText();
+ String authToken = responseObject.get("authorization").asText();
+ if (dataPlaneEndpoint != null && authToken != null) {
+ EdrDto edr = new EdrDto("Authorization", authToken, dataPlaneEndpoint);
+ log.debug("Requested EDR successfully: {}", edr);
+ failed = false;
+ return edr;
+ }
+ }
+ } catch (Exception e) {
log.error("EDR token for transfer process with ID {} could not be obtained", transferProcessId);
+ } finally {
+ if (failed && --retries >= 0) {
+ try {
+ Thread.sleep(100);
+ } catch (Exception e1) {
+ log.error("Sleep interrupted", e1);
+ }
+ }
}
+ return getEdrForTransferProcessId(transferProcessId, retries);
- return null;
}
/**
diff --git a/backend/src/main/java/org/eclipse/tractusx/puris/backend/delivery/logic/adapter/DeliveryInformationSammMapper.java b/backend/src/main/java/org/eclipse/tractusx/puris/backend/delivery/logic/adapter/DeliveryInformationSammMapper.java
index 46629942..60e51a18 100644
--- a/backend/src/main/java/org/eclipse/tractusx/puris/backend/delivery/logic/adapter/DeliveryInformationSammMapper.java
+++ b/backend/src/main/java/org/eclipse/tractusx/puris/backend/delivery/logic/adapter/DeliveryInformationSammMapper.java
@@ -53,17 +53,12 @@ public class DeliveryInformationSammMapper {
@Autowired
private MaterialService materialService;
- public DeliveryInformation ownDeliveryToSamm(List deliveryList) {
- if (deliveryList == null || deliveryList.isEmpty()) {
- log.warn("Can't map empty list");
- return null;
- }
- Partner partner = deliveryList.get(0).getPartner();
+ public DeliveryInformation ownDeliveryToSamm(List deliveryList, Partner partner, Material material) {
if (deliveryList.stream().anyMatch(deli -> !deli.getPartner().equals(partner))) {
log.warn("Can't map delivery list with different partners");
return null;
}
- Material material = deliveryList.get(0).getMaterial();
+
if (deliveryList.stream().anyMatch(deli -> !deli.getMaterial().equals(material))) {
log.warn("Can't map delivery list with different materials");
return null;
diff --git a/backend/src/main/java/org/eclipse/tractusx/puris/backend/delivery/logic/service/DeliveryRequestApiService.java b/backend/src/main/java/org/eclipse/tractusx/puris/backend/delivery/logic/service/DeliveryRequestApiService.java
index c4c9b1da..11eb0919 100644
--- a/backend/src/main/java/org/eclipse/tractusx/puris/backend/delivery/logic/service/DeliveryRequestApiService.java
+++ b/backend/src/main/java/org/eclipse/tractusx/puris/backend/delivery/logic/service/DeliveryRequestApiService.java
@@ -22,15 +22,11 @@
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
-
-import java.util.Optional;
-
import org.eclipse.tractusx.puris.backend.common.edc.domain.model.SubmodelType;
import org.eclipse.tractusx.puris.backend.common.edc.logic.service.EdcAdapterService;
import org.eclipse.tractusx.puris.backend.delivery.logic.adapter.DeliveryInformationSammMapper;
import org.eclipse.tractusx.puris.backend.delivery.logic.dto.deliverysamm.DeliveryInformation;
import org.eclipse.tractusx.puris.backend.masterdata.domain.model.Material;
-import org.eclipse.tractusx.puris.backend.masterdata.domain.model.MaterialPartnerRelation;
import org.eclipse.tractusx.puris.backend.masterdata.domain.model.Partner;
import org.eclipse.tractusx.puris.backend.masterdata.logic.service.MaterialPartnerRelationService;
import org.eclipse.tractusx.puris.backend.masterdata.logic.service.MaterialService;
@@ -39,6 +35,8 @@
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
+import java.util.Optional;
+
@Service
@Slf4j
/**
@@ -68,22 +66,41 @@ public DeliveryInformation handleDeliverySubmodelRequest(String bpnl, String mat
log.error("Unknown Partner BPNL " + bpnl);
return null;
}
- MaterialPartnerRelation mpr = mprService.findByPartnerAndPartnerCXNumber(partner, materialNumberCx);
+
Material material = materialService.findByMaterialNumberCx(materialNumberCx);
- if (material == null && mpr == null) {
+ if (material == null) {
+ // Could not identify partner cx number. I.e. we do not have that partner's
+ // CX id in one of our MaterialPartnerRelation entities. Try to fix this by
+ // looking for MPR's, where that partner is a supplier and where we don't have
+ // a partnerCXId yet. Of course this can only work if there was previously an MPR
+ // created, but for some unforeseen reason, the initial PartTypeRetrieval didn't succeed.
+ log.warn("Could not find " + materialNumberCx + " from partner " + partner.getBpnl());
+ mprService.triggerPartTypeRetrievalTask(partner);
+ material = materialService.findByMaterialNumberCx(materialNumberCx);
+ }
+
+ if (material == null) {
log.error("Unknown Material " + materialNumberCx);
return null;
}
- if (material == null) {
- material = mpr.getMaterial();
+
+ var mpr = mprService.find(material,partner);
+ if (mpr == null || !mpr.isPartnerSuppliesMaterial()) {
+ // only send an answer if partner is registered as supplier
+ return null;
}
+
var currentDeliveries = ownDeliveryService.findAllByFilters(Optional.of(material.getOwnMaterialNumber()), Optional.empty(), Optional.of(partner.getBpnl()));
- return sammMapper.ownDeliveryToSamm(currentDeliveries);
+ return sammMapper.ownDeliveryToSamm(currentDeliveries, partner, material);
}
public void doReportedDeliveryRequest(Partner partner, Material material) {
try {
var mpr = mprService.find(material, partner);
+ if (mpr.getPartnerCXNumber() == null) {
+ mprService.triggerPartTypeRetrievalTask(partner);
+ mpr = mprService.find(material, partner);
+ }
var direction = material.isMaterialFlag() ? DirectionCharacteristic.OUTBOUND : DirectionCharacteristic.INBOUND;
var data = edcAdapterService.doSubmodelRequest(SubmodelType.DELIVERY, mpr, direction, 1);
var samm = objectMapper.treeToValue(data, DeliveryInformation.class);
diff --git a/backend/src/main/java/org/eclipse/tractusx/puris/backend/demand/logic/adapter/ShortTermMaterialDemandSammMapper.java b/backend/src/main/java/org/eclipse/tractusx/puris/backend/demand/logic/adapter/ShortTermMaterialDemandSammMapper.java
index 1454aca0..7deea4d8 100644
--- a/backend/src/main/java/org/eclipse/tractusx/puris/backend/demand/logic/adapter/ShortTermMaterialDemandSammMapper.java
+++ b/backend/src/main/java/org/eclipse/tractusx/puris/backend/demand/logic/adapter/ShortTermMaterialDemandSammMapper.java
@@ -50,13 +50,7 @@ public class ShortTermMaterialDemandSammMapper {
@Autowired
private MaterialService materialService;
- public ShortTermMaterialDemand ownDemandToSamm(List demandList) {
- if (demandList == null || demandList.isEmpty()) {
- log.warn("Can't map empty list");
- return null;
- }
- Partner partner = demandList.get(0).getPartner();
- Material material = demandList.get(0).getMaterial();
+ public ShortTermMaterialDemand ownDemandToSamm(List demandList,Partner partner, Material material) {
if (demandList.stream().anyMatch(dem -> !dem.getPartner().equals(partner))) {
log.warn("Can't map demand list with different partners");
return null;
diff --git a/backend/src/main/java/org/eclipse/tractusx/puris/backend/demand/logic/services/DemandRequestApiService.java b/backend/src/main/java/org/eclipse/tractusx/puris/backend/demand/logic/services/DemandRequestApiService.java
index 840460b7..c3811da1 100644
--- a/backend/src/main/java/org/eclipse/tractusx/puris/backend/demand/logic/services/DemandRequestApiService.java
+++ b/backend/src/main/java/org/eclipse/tractusx/puris/backend/demand/logic/services/DemandRequestApiService.java
@@ -22,9 +22,6 @@
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
-
-import java.util.Optional;
-
import org.eclipse.tractusx.puris.backend.common.edc.domain.model.SubmodelType;
import org.eclipse.tractusx.puris.backend.common.edc.logic.service.EdcAdapterService;
import org.eclipse.tractusx.puris.backend.demand.logic.adapter.ShortTermMaterialDemandSammMapper;
@@ -37,6 +34,8 @@
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
+import java.util.Optional;
+
@Service
@Slf4j
/**
@@ -65,17 +64,39 @@ public ShortTermMaterialDemand handleDemandSubmodelRequest(String bpnl, String m
return null;
}
Material material = mprService.findByPartnerAndPartnerCXNumber(partner, materialNumberCx).getMaterial();
+
+ if (material == null) {
+ // Could not identify partner cx number. I.e. we do not have that partner's
+ // CX id in one of our MaterialPartnerRelation entities. Try to fix this by
+ // looking for MPR's, where that partner is a supplier and where we don't have
+ // a partnerCXId yet. Of course this can only work if there was previously an MPR
+ // created, but for some unforeseen reason, the initial PartTypeRetrieval didn't succeed.
+ log.warn("Could not find " + materialNumberCx + " from partner " + partner.getBpnl());
+ mprService.triggerPartTypeRetrievalTask(partner);
+ material = mprService.findByPartnerAndPartnerCXNumber(partner, materialNumberCx).getMaterial();
+ }
+
if (material == null) {
log.error("Unknown Material");
return null;
}
+ var mpr = mprService.find(material,partner);
+ if (mpr == null || !mpr.isPartnerSuppliesMaterial()) {
+ // only send an answer if partner is registered as supplier
+ return null;
+ }
+
var currentDemands = ownDemandService.findAllByFilters(Optional.of(material.getOwnMaterialNumber()), Optional.of(partner.getBpnl()), Optional.empty());
- return sammMapper.ownDemandToSamm(currentDemands);
+ return sammMapper.ownDemandToSamm(currentDemands, partner, material);
}
public void doReportedDemandRequest(Partner partner, Material material) {
try {
var mpr = mprService.find(material, partner);
+ if (mpr.getPartnerCXNumber() == null) {
+ mprService.triggerPartTypeRetrievalTask(partner);
+ mpr = mprService.find(material, partner);
+ }
var data = edcAdapterService.doSubmodelRequest(SubmodelType.DEMAND, mpr, DirectionCharacteristic.INBOUND, 1);
var samm = objectMapper.treeToValue(data, ShortTermMaterialDemand.class);
var demands = sammMapper.sammToReportedDemand(samm, partner);
diff --git a/backend/src/main/java/org/eclipse/tractusx/puris/backend/masterdata/logic/service/MaterialPartnerRelationService.java b/backend/src/main/java/org/eclipse/tractusx/puris/backend/masterdata/logic/service/MaterialPartnerRelationService.java
index c8d3e7a2..df03d0d7 100644
--- a/backend/src/main/java/org/eclipse/tractusx/puris/backend/masterdata/logic/service/MaterialPartnerRelationService.java
+++ b/backend/src/main/java/org/eclipse/tractusx/puris/backend/masterdata/logic/service/MaterialPartnerRelationService.java
@@ -33,7 +33,7 @@
public interface MaterialPartnerRelationService {
MaterialPartnerRelation create(MaterialPartnerRelation materialPartnerRelation);
- void triggerPartTypeRetrievalTask(MaterialPartnerRelation mpr);
+ void triggerPartTypeRetrievalTask(Partner supplierPartner);
MaterialPartnerRelation update(MaterialPartnerRelation materialPartnerRelation);
diff --git a/backend/src/main/java/org/eclipse/tractusx/puris/backend/masterdata/logic/service/MaterialPartnerRelationServiceImpl.java b/backend/src/main/java/org/eclipse/tractusx/puris/backend/masterdata/logic/service/MaterialPartnerRelationServiceImpl.java
index 8f75ee15..fcb1c900 100644
--- a/backend/src/main/java/org/eclipse/tractusx/puris/backend/masterdata/logic/service/MaterialPartnerRelationServiceImpl.java
+++ b/backend/src/main/java/org/eclipse/tractusx/puris/backend/masterdata/logic/service/MaterialPartnerRelationServiceImpl.java
@@ -23,7 +23,6 @@
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
-import org.eclipse.tractusx.puris.backend.common.ddtr.logic.DigitalTwinMappingService;
import org.eclipse.tractusx.puris.backend.common.ddtr.logic.DtrAdapterService;
import org.eclipse.tractusx.puris.backend.common.edc.logic.service.EdcAdapterService;
import org.eclipse.tractusx.puris.backend.common.util.PatternStore;
@@ -54,9 +53,6 @@ public class MaterialPartnerRelationServiceImpl implements MaterialPartnerRelati
@Autowired
private VariablesService variablesService;
- @Autowired
- private DigitalTwinMappingService dtmService;
-
@Autowired
private DtrAdapterService dtrAdapterService;
@@ -86,23 +82,45 @@ public MaterialPartnerRelation create(MaterialPartnerRelation materialPartnerRel
var searchResult = find(materialPartnerRelation.getMaterial(), materialPartnerRelation.getPartner());
if (searchResult == null) {
executorService.submit(new DtrRegistrationTask(materialPartnerRelation, 3));
- if (materialPartnerRelation.getMaterial().isMaterialFlag() && materialPartnerRelation.isPartnerSuppliesMaterial()
- && materialPartnerRelation.getPartnerCXNumber() == null) {
- log.info("Attempting CX-Id fetch for Material " + materialPartnerRelation.getMaterial().getOwnMaterialNumber() +
- " from Supplier-Partner " + materialPartnerRelation.getPartner().getBpnl());
- executorService.submit(new PartTypeInformationRetrievalTask(materialPartnerRelation, 1));
- }
return mprRepository.save(materialPartnerRelation);
}
log.error("Could not create MaterialPartnerRelation, " + materialPartnerRelation.getKey() + " already exists");
return null;
}
+ /**
+ * Call this method when a partnerCXId for a Material was needed but not found.
+ * This method will trigger a new PartTypeInformation Task for any material that
+ * the given partner supplies, but still misses a partnerCXId.
+ *
+ * This method will block until all tasks have finished, if any.
+ *
+ * @param supplierPartner The supplier partner
+ */
@Override
- public void triggerPartTypeRetrievalTask(MaterialPartnerRelation mpr) {
- if (!currentPartTypeFetches.contains(mpr)) {
- executorService.submit(new PartTypeInformationRetrievalTask(mpr, 1));
+ public void triggerPartTypeRetrievalTask(Partner supplierPartner) {
+ List> futures = mprRepository
+ .findAllByPartner_UuidAndPartnerSuppliesMaterialIsTrue(supplierPartner.getUuid())
+ .stream()
+ .filter(mpr -> mpr.getPartnerCXNumber() == null)
+ .filter(mpr -> !currentPartTypeFetches.contains(mpr))
+ .map(mpr -> executorService.submit(new PartTypeInformationRetrievalTask(mpr, 1)))
+ .toList();
+ if (futures.isEmpty()) {
+ return;
}
+
+ do {
+ Thread.yield();
+ // wait until all triggered tasks have returned
+ } while (!futures.stream().allMatch(Future::isDone));
+
+ // give the database a little bit of time to handle the updates
+ try {
+ Thread.sleep(400);
+ } catch (InterruptedException ignored) {
+ }
+
}
@@ -144,7 +162,7 @@ private class PartTypeInformationRetrievalTask implements Callable {
/**
* This method contains all the duties which the PartTypeInformationRetrievalTask is trying to fulfill.
*
- * @return true, if the task finished successfully
+ * @return true, if the task finished successfully
*/
@Override
public Boolean call() {
@@ -242,7 +260,7 @@ public DtrRegistrationTask(MaterialPartnerRelation materialPartnerRelation, int
/**
* This method contains all the duties which the DtrRegistrationTask is trying to fulfill.
*
- * @return true, if the task finished successfully
+ * @return true, if the task finished successfully
*/
@Override
public Boolean call() throws Exception {
@@ -268,9 +286,12 @@ public Boolean call() throws Exception {
completedProductRegistration = true;
} else {
if (result == 404) {
- Integer registrationResult = dtrAdapterService.registerProductAtDtr(materialPartnerRelation.getMaterial());
+ Integer registrationResult = dtrAdapterService.registerProductAtDtr(materialPartnerRelation.getMaterial(), allCustomers);
log.info("Tried to create product AAS for " + materialPartnerRelation.getMaterial().getOwnMaterialNumber()
+ ", result: " + registrationResult);
+ if (registrationResult != null && registrationResult < 400) {
+ completedProductRegistration = true;
+ }
}
}
} else {
@@ -351,12 +372,6 @@ public MaterialPartnerRelation update(MaterialPartnerRelation materialPartnerRel
flagConsistencyTest(materialPartnerRelation);
var foundEntity = mprRepository.findById(materialPartnerRelation.getKey());
if (foundEntity.isPresent()) {
- if (materialPartnerRelation.getMaterial().isMaterialFlag() && materialPartnerRelation.isPartnerSuppliesMaterial()
- && materialPartnerRelation.getPartnerCXNumber() == null) {
- log.info("Attempting CX-Id fetch for Material " + materialPartnerRelation.getMaterial().getOwnMaterialNumber() +
- " from Supplier-Partner " + materialPartnerRelation.getPartner().getBpnl());
- executorService.submit(new PartTypeInformationRetrievalTask(materialPartnerRelation, 3));
- }
executorService.submit(new DtrRegistrationTask(materialPartnerRelation, 3));
return mprRepository.save(materialPartnerRelation);
}
diff --git a/backend/src/main/java/org/eclipse/tractusx/puris/backend/production/logic/adapter/PlannedProductionSammMapper.java b/backend/src/main/java/org/eclipse/tractusx/puris/backend/production/logic/adapter/PlannedProductionSammMapper.java
index 3d1b8f9d..42e3a5e8 100644
--- a/backend/src/main/java/org/eclipse/tractusx/puris/backend/production/logic/adapter/PlannedProductionSammMapper.java
+++ b/backend/src/main/java/org/eclipse/tractusx/puris/backend/production/logic/adapter/PlannedProductionSammMapper.java
@@ -42,13 +42,7 @@ public class PlannedProductionSammMapper {
@Autowired
private MaterialPartnerRelationService mprService;
- public PlannedProductionOutput ownProductionToSamm(List production) {
- if (production == null || production.isEmpty()) {
- log.warn("Can't map empty list");
- return null;
- }
- Partner partner = production.get(0).getPartner();
- Material material = production.get(0).getMaterial();
+ public PlannedProductionOutput ownProductionToSamm(List production, Partner partner, Material material) {
if (production.stream().anyMatch(prod -> !prod.getPartner().equals(partner))) {
log.warn("Can't map production list with different partners");
return null;
diff --git a/backend/src/main/java/org/eclipse/tractusx/puris/backend/production/logic/service/ProductionRequestApiService.java b/backend/src/main/java/org/eclipse/tractusx/puris/backend/production/logic/service/ProductionRequestApiService.java
index 4f31b837..3aa173b6 100644
--- a/backend/src/main/java/org/eclipse/tractusx/puris/backend/production/logic/service/ProductionRequestApiService.java
+++ b/backend/src/main/java/org/eclipse/tractusx/puris/backend/production/logic/service/ProductionRequestApiService.java
@@ -22,9 +22,6 @@
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
-
-import java.util.Optional;
-
import org.eclipse.tractusx.puris.backend.common.edc.domain.model.SubmodelType;
import org.eclipse.tractusx.puris.backend.common.edc.logic.service.EdcAdapterService;
import org.eclipse.tractusx.puris.backend.masterdata.domain.model.Material;
@@ -38,6 +35,8 @@
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
+import java.util.Optional;
+
@Service
@Slf4j
/**
@@ -70,8 +69,12 @@ public PlannedProductionOutput handleProductionSubmodelRequest(String bpnl, Stri
if (material == null) {
return null;
}
+ if (!mprService.find(material, partner).isPartnerBuysMaterial()) {
+ // only send an answer if partner is registered as customer
+ return null;
+ }
var currentProduction = ownProductionService.findAllByFilters(Optional.of(material.getOwnMaterialNumber()), Optional.of(partner.getBpnl()), Optional.empty());
- return sammMapper.ownProductionToSamm(currentProduction);
+ return sammMapper.ownProductionToSamm(currentProduction, partner, material);
}
public void doReportedProductionRequest(Partner partner, Material material) {
diff --git a/backend/src/main/java/org/eclipse/tractusx/puris/backend/stock/logic/adapter/ItemStockSammMapper.java b/backend/src/main/java/org/eclipse/tractusx/puris/backend/stock/logic/adapter/ItemStockSammMapper.java
index 496d7814..d8ea0471 100644
--- a/backend/src/main/java/org/eclipse/tractusx/puris/backend/stock/logic/adapter/ItemStockSammMapper.java
+++ b/backend/src/main/java/org/eclipse/tractusx/puris/backend/stock/logic/adapter/ItemStockSammMapper.java
@@ -45,21 +45,15 @@ public class ItemStockSammMapper {
@Autowired
private MaterialPartnerRelationService mprService;
- public ItemStockSamm materialItemStocksToItemStockSamm(List materialItemStocks) {
- return listToItemStockSamm(materialItemStocks, DirectionCharacteristic.INBOUND);
+ public ItemStockSamm materialItemStocksToItemStockSamm(List materialItemStocks, Partner partner, Material material) {
+ return listToItemStockSamm(materialItemStocks, DirectionCharacteristic.INBOUND, partner, material);
}
- public ItemStockSamm productItemStocksToItemStockSamm(List productItemStocks) {
- return listToItemStockSamm(productItemStocks, DirectionCharacteristic.OUTBOUND);
+ public ItemStockSamm productItemStocksToItemStockSamm(List productItemStocks, Partner partner, Material material) {
+ return listToItemStockSamm(productItemStocks, DirectionCharacteristic.OUTBOUND, partner, material);
}
- private ItemStockSamm listToItemStockSamm(List extends ItemStock> itemStocks, DirectionCharacteristic directionCharacteristic) {
- if (itemStocks == null || itemStocks.isEmpty()) {
- log.warn("Can't map empty list");
- return null;
- }
- Partner partner = itemStocks.get(0).getPartner();
- Material material = itemStocks.get(0).getMaterial();
+ private ItemStockSamm listToItemStockSamm(List extends ItemStock> itemStocks, DirectionCharacteristic directionCharacteristic, Partner partner, Material material) {
if (itemStocks.stream().anyMatch(stock -> !stock.getPartner().equals(partner))) {
log.warn("Can't map item stock list with different partners");
return null;
diff --git a/backend/src/main/java/org/eclipse/tractusx/puris/backend/stock/logic/service/ItemStockRequestApiService.java b/backend/src/main/java/org/eclipse/tractusx/puris/backend/stock/logic/service/ItemStockRequestApiService.java
index 95d20f62..1007a949 100644
--- a/backend/src/main/java/org/eclipse/tractusx/puris/backend/stock/logic/service/ItemStockRequestApiService.java
+++ b/backend/src/main/java/org/eclipse/tractusx/puris/backend/stock/logic/service/ItemStockRequestApiService.java
@@ -73,9 +73,10 @@ public ItemStockSamm handleItemStockSubmodelRequest(String bpnl, String material
// Partner is customer, requesting our ProductItemStocks for him
// materialNumber is own CX id:
Material material = materialService.findByMaterialNumberCx(materialNumber);
- if (material != null) {
+ if (material != null && mprService.find(material, partner).isPartnerBuysMaterial()) {
+ // only send an answer if partner is registered as customer
var currentStocks = productItemStockService.findByPartnerAndMaterial(partner, material);
- return sammMapper.productItemStocksToItemStockSamm(currentStocks);
+ return sammMapper.productItemStocksToItemStockSamm(currentStocks, partner, material);
}
return null;
}
@@ -83,21 +84,31 @@ public ItemStockSamm handleItemStockSubmodelRequest(String bpnl, String material
// Partner is supplier, requesting our MaterialItemStocks from him
// materialNumber is partner's CX id:
Material material = mprService.findByPartnerAndPartnerCXNumber(partner, materialNumber).getMaterial();
- if (material != null) {
- var currentStocks = materialItemStockService.findByPartnerAndMaterial(partner, material);
- return sammMapper.materialItemStocksToItemStockSamm(currentStocks);
+ if (material == null) {
+ // Could not identify partner cx number. I.e. we do not have that partner's
+ // CX id in one of our MaterialPartnerRelation entities. Try to fix this by
+ // looking for MPR's, where that partner is a supplier and where we don't have
+ // a partnerCXId yet. Of course this can only work if there was previously an MPR
+ // created, but for some unforeseen reason, the initial PartTypeRetrieval didn't succeed.
+ log.warn("Could not find " + materialNumber + " from partner " + partner.getBpnl());
+ mprService.triggerPartTypeRetrievalTask(partner);
+ material = mprService.findByPartnerAndPartnerCXNumber(partner, materialNumber).getMaterial();
}
- // Could not identify partner cx number. I.e. we do not have that partner's
- // CX id in one of our MaterialPartnerRelation entities. Try to fix this by
- // looking for MPR's, where that partner is a supplier and where we don't have
- // a partnerCXId yet. Of course this can only work if there was previously an MPR
- // created, but for some unforeseen reason, the initial PartTypeRetrieval didn't succeed.
- log.warn("Could not find " + materialNumber + " from partner " + partner.getBpnl());
- mprService.findAllMaterialsThatPartnerSupplies(partner).stream()
- .map(mat -> mprService.find(mat, partner))
- .filter(mpr -> mpr.isPartnerSuppliesMaterial() && mpr.getPartnerCXNumber() == null)
- .forEach(mpr -> mprService.triggerPartTypeRetrievalTask(mpr));
- return null;
+
+ if (material == null) {
+ log.error("Unknown Material");
+ return null;
+ }
+ var mpr = mprService.find(material, partner);
+ if (mpr == null || !mpr.isPartnerSuppliesMaterial()) {
+ // only send an answer if partner is registered as supplier
+ return null;
+ }
+
+ // only send an answer if partner is registered as supplier
+ var currentStocks = materialItemStockService.findByPartnerAndMaterial(partner, material);
+ return sammMapper.materialItemStocksToItemStockSamm(currentStocks, partner, material);
+
}
default -> {
return null;
@@ -136,6 +147,10 @@ public void doItemStockSubmodelReportedMaterialItemStockRequest(Partner partner,
public void doItemStockSubmodelReportedProductItemStockRequest(Partner partner, Material material) {
try {
var mpr = mprService.find(material, partner);
+ if (mpr.getPartnerCXNumber() == null) {
+ mprService.triggerPartTypeRetrievalTask(partner);
+ mpr = mprService.find(material, partner);
+ }
var data = edcAdapterService.doSubmodelRequest(SubmodelType.ITEM_STOCK ,mpr, DirectionCharacteristic.INBOUND, 1);
var samm = objectMapper.treeToValue(data, ItemStockSamm.class);
var stocks = sammMapper.itemStockSammToReportedProductItemStock(samm, partner);
diff --git a/backend/src/test/java/org/eclipse/tractusx/puris/backend/stock/logic/adapter/ItemStockSammMapperTest.java b/backend/src/test/java/org/eclipse/tractusx/puris/backend/stock/logic/adapter/ItemStockSammMapperTest.java
index a161adad..9ded3672 100644
--- a/backend/src/test/java/org/eclipse/tractusx/puris/backend/stock/logic/adapter/ItemStockSammMapperTest.java
+++ b/backend/src/test/java/org/eclipse/tractusx/puris/backend/stock/logic/adapter/ItemStockSammMapperTest.java
@@ -145,7 +145,7 @@ void map_WhenSingleMaterialItemStock_ReturnsItemStockSamm() {
// These should result in two positions
// - one WITHOUT orderPositionReference AND two allocatedStocks
// - one WITH orderPosition AND one allocatedStocks
- ItemStockSamm materialItemStockSamm = itemStockSammMapper.materialItemStocksToItemStockSamm(List.of(materialItemStock));
+ ItemStockSamm materialItemStockSamm = itemStockSammMapper.materialItemStocksToItemStockSamm(List.of(materialItemStock), supplierPartner, semiconductorMaterial);
// Then
assertNotNull(materialItemStockSamm);
diff --git a/charts/puris/Chart.yaml b/charts/puris/Chart.yaml
index b6880ece..1292ec74 100644
--- a/charts/puris/Chart.yaml
+++ b/charts/puris/Chart.yaml
@@ -35,10 +35,10 @@ dependencies:
# This is the chart version. This version number should be incremented each time you make changes
# to the chart and its templates, including the app version.
# Versions are expected to follow Semantic Versioning (https://semver.org/)
-version: 2.6.0
+version: 2.6.1
# This is the version number of the application being deployed. This version number should be
# incremented each time you make changes to the application. Versions are not expected to
# follow Semantic Versioning. They should reflect the version the application is using.
# It is recommended to use it with quotes.
-appVersion: "2.0.0"
+appVersion: "2.0.1"
diff --git a/charts/puris/README.md b/charts/puris/README.md
index ef810be3..d345bb9c 100644
--- a/charts/puris/README.md
+++ b/charts/puris/README.md
@@ -1,12 +1,13 @@
# puris
-![Version: 2.6.0](https://img.shields.io/badge/Version-2.6.0-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: 2.0.0](https://img.shields.io/badge/AppVersion-2.0.0-informational?style=flat-square)
+![Version: 2.6.1](https://img.shields.io/badge/Version-2.6.1-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: 2.0.1](https://img.shields.io/badge/AppVersion-2.0.1-informational?style=flat-square)
A helm chart for Kubernetes deployment of PURIS
**Homepage:**
## Prerequisites
+
- Kubernetes 1.19+
- Helm 3.2.0+