From b16a5df93d8c608d31e80eb3bf92195aecb99109 Mon Sep 17 00:00:00 2001 From: ds-ext-sceronik Date: Wed, 17 Jan 2024 08:55:46 +0100 Subject: [PATCH] bug(tx-backend): #546 fix issue with one type of bom lifecycle in import file --- .../AssetAsBuiltRepositoryImpl.java | 4 +- .../AssetAsPlannedRepositoryImpl.java | 3 + .../importdata/ImportControllerIT.java | 55 ++++++++++++ .../validImportFile-onlyAsBuiltAsset.json | 88 +++++++++++++++++++ .../validImportFile-onlyAsPlannedAsset.json | 62 +++++++++++++ 5 files changed, 211 insertions(+), 1 deletion(-) create mode 100644 tx-backend/src/test/resources/testdata/importfiles/validImportFile-onlyAsBuiltAsset.json create mode 100644 tx-backend/src/test/resources/testdata/importfiles/validImportFile-onlyAsPlannedAsset.json diff --git a/tx-backend/src/main/java/org/eclipse/tractusx/traceability/assets/infrastructure/asbuilt/repository/AssetAsBuiltRepositoryImpl.java b/tx-backend/src/main/java/org/eclipse/tractusx/traceability/assets/infrastructure/asbuilt/repository/AssetAsBuiltRepositoryImpl.java index 418778053a..4b7a87f22a 100644 --- a/tx-backend/src/main/java/org/eclipse/tractusx/traceability/assets/infrastructure/asbuilt/repository/AssetAsBuiltRepositoryImpl.java +++ b/tx-backend/src/main/java/org/eclipse/tractusx/traceability/assets/infrastructure/asbuilt/repository/AssetAsBuiltRepositoryImpl.java @@ -102,7 +102,9 @@ public List saveAll(List assets) { @Override @Transactional public List saveAllIfNotInIRSSyncAndUpdateImportStateAndNote(List assets) { - + if(Objects.isNull(assets)) { + return List.of(); + } List toPersist = assets.stream().map(assetToPersist -> new AbstractMap.SimpleEntry(assetToPersist, jpaAssetAsBuiltRepository.findById(assetToPersist.getId()).orElse(null))) .filter(this::entityIsTransientOrNotExistent) .map(entry -> { diff --git a/tx-backend/src/main/java/org/eclipse/tractusx/traceability/assets/infrastructure/asplanned/repository/AssetAsPlannedRepositoryImpl.java b/tx-backend/src/main/java/org/eclipse/tractusx/traceability/assets/infrastructure/asplanned/repository/AssetAsPlannedRepositoryImpl.java index 2e2b4d13e7..33f0a8dfc3 100644 --- a/tx-backend/src/main/java/org/eclipse/tractusx/traceability/assets/infrastructure/asplanned/repository/AssetAsPlannedRepositoryImpl.java +++ b/tx-backend/src/main/java/org/eclipse/tractusx/traceability/assets/infrastructure/asplanned/repository/AssetAsPlannedRepositoryImpl.java @@ -102,6 +102,9 @@ public List saveAll(List assets) { @Override @Transactional public List saveAllIfNotInIRSSyncAndUpdateImportStateAndNote(List assets) { + if(Objects.isNull(assets)) { + return List.of(); + } List toPersist = assets.stream().map(assetToPersist -> new AbstractMap.SimpleEntry( assetToPersist, diff --git a/tx-backend/src/test/java/org/eclipse/tractusx/traceability/integration/importdata/ImportControllerIT.java b/tx-backend/src/test/java/org/eclipse/tractusx/traceability/integration/importdata/ImportControllerIT.java index 26e4ce7c9f..c99e8919fa 100644 --- a/tx-backend/src/test/java/org/eclipse/tractusx/traceability/integration/importdata/ImportControllerIT.java +++ b/tx-backend/src/test/java/org/eclipse/tractusx/traceability/integration/importdata/ImportControllerIT.java @@ -28,6 +28,8 @@ import org.eclipse.tractusx.traceability.assets.domain.base.model.QualityType; import org.eclipse.tractusx.traceability.assets.infrastructure.asbuilt.model.AssetAsBuiltEntity; import org.eclipse.tractusx.traceability.assets.infrastructure.asbuilt.repository.JpaAssetAsBuiltRepository; +import org.eclipse.tractusx.traceability.assets.infrastructure.asplanned.model.AssetAsPlannedEntity; +import org.eclipse.tractusx.traceability.assets.infrastructure.asplanned.repository.JpaAssetAsPlannedRepository; import org.eclipse.tractusx.traceability.common.security.JwtRole; import org.eclipse.tractusx.traceability.integration.IntegrationTestSpecification; import org.hamcrest.Matchers; @@ -49,6 +51,9 @@ class ImportControllerIT extends IntegrationTestSpecification { @Autowired JpaAssetAsBuiltRepository jpaAssetAsBuiltRepository; + @Autowired + JpaAssetAsPlannedRepository jpaAssetAsPlannedRepository; + @Test void givenValidFile_whenImportData_thenValidationShouldPass() throws JoseException { // given @@ -91,6 +96,56 @@ void givenValidFile_whenImportData_thenValidationShouldPass() throws JoseExcepti assertThat(entity.getSubmodels()).isNotEmpty(); } + @Test + void givenValidFileWithAsBuiltOnly_whenImportData_thenValidationShouldPass() throws JoseException { + // given + String path = getClass().getResource("/testdata/importfiles/validImportFile-onlyAsBuiltAsset.json").getFile(); + File file = new File(path); + + // when/then + ImportResponse result = given() + .header(oAuth2Support.jwtAuthorization(JwtRole.ADMIN)) + .when() + .multiPart(file) + .post("/api/assets/import") + .then() + .statusCode(200) + .extract().as(ImportResponse.class); + + assertThat(result.validationResult().validationErrors()).isEmpty(); + assertThat(result.importStateMessage()).containsExactlyInAnyOrder( + new ImportStateMessage("urn:uuid:6b2296cc-26c0-4f38-8a22-092338c36111", true) + ); + + AssetAsBuiltEntity entity = jpaAssetAsBuiltRepository.findById("urn:uuid:6b2296cc-26c0-4f38-8a22-092338c36111").get(); + assertThat(entity.getSubmodels()).isNotEmpty(); + } + + @Test + void givenValidFileWithAsPlannedOnly_whenImportData_thenValidationShouldPass() throws JoseException { + // given + String path = getClass().getResource("/testdata/importfiles/validImportFile-onlyAsPlannedAsset.json").getFile(); + File file = new File(path); + + // when/then + ImportResponse result = given() + .header(oAuth2Support.jwtAuthorization(JwtRole.ADMIN)) + .when() + .multiPart(file) + .post("/api/assets/import") + .then() + .statusCode(200) + .extract().as(ImportResponse.class); + + assertThat(result.validationResult().validationErrors()).isEmpty(); + assertThat(result.importStateMessage()).containsExactlyInAnyOrder( + new ImportStateMessage("urn:uuid:0733946c-59c6-41ae-9570-cb43a6e4eb01", true) + ); + + AssetAsPlannedEntity entity = jpaAssetAsPlannedRepository.findById("urn:uuid:0733946c-59c6-41ae-9570-cb43a6e4eb01").get(); + assertThat(entity.getSubmodels()).isNotEmpty(); + } + @Test void givenValidFile_whenImportDataButAssetExistInPersistentImportState_thenValidationShouldPassAndExpectedResponse() throws JoseException { // given diff --git a/tx-backend/src/test/resources/testdata/importfiles/validImportFile-onlyAsBuiltAsset.json b/tx-backend/src/test/resources/testdata/importfiles/validImportFile-onlyAsBuiltAsset.json new file mode 100644 index 0000000000..218c056bda --- /dev/null +++ b/tx-backend/src/test/resources/testdata/importfiles/validImportFile-onlyAsBuiltAsset.json @@ -0,0 +1,88 @@ +{ + "assets": [ + { + "assetMetaInfo": { + "catenaXId": "urn:uuid:6b2296cc-26c0-4f38-8a22-092338c36111" + }, + "submodels": [ + { + "aspectType": "urn:bamm:io.catenax.serial_part:1.0.1#SerialPart", + "payload": { + "localIdentifiers": [ + { + "value": "BPNL00000003AXS3", + "key": "manufacturerId" + }, + { + "value": "3500011-11", + "key": "manufacturerPartId" + }, + { + "value": "OMAOYGBDTSRCMYSCX", + "key": "partInstanceId" + }, + { + "value": "OMAOYGBDTSRCMYSCX", + "key": "van" + } + ], + "manufacturingInformation": { + "date": "2024-01-15T04:15:57.000Z", + "country": "DEU" + }, + "catenaXId": "urn:uuid:6b2296cc-26c0-4f38-8a22-092338c36111", + "partTypeInformation": { + "manufacturerPartId": "3500011-11", + "classification": "product", + "nameAtManufacturer": "a/dev Test Produkt AB" + } + } + }, + { + "aspectType": "urn:bamm:io.catenax.single_level_bom_as_built:2.0.0#SingleLevelBomAsBuilt", + "payload": { + "catenaXId": "urn:uuid:6b2296cc-26c0-4f38-8a22-092338c36111", + "childItems": [ + { + "quantity": { + "quantityNumber": 1, + "measurementUnit": "unit:piece" + }, + "hasAlternatives": true, + "createdOn": "2022-02-03T14:48:54.709Z", + "lastModifiedOn": "2022-02-03T14:48:54.709Z", + "catenaXId": "urn:uuid:7eeeac86-7b69-444d-81e6-655d0f1513bd", + "businessPartner": "BPNL00000003CNKC" + } + ] + } + }, + { + "aspectType": "urn:bamm:io.catenax.single_level_usage_as_built:2.0.0#SingleLevelUsageAsBuilt", + "payload": { + "catenaXId": "urn:uuid:6b2296cc-26c0-4f38-8a22-092338c36111", + "customers": [ + { + "parentItems": [ + { + "quantity": { + "quantityNumber": 1, + "measurementUnit": "unit:piece" + }, + "catenaXId": "urn:uuid:f11ddc62-3bd5-468f-b7b0-110fe13ed0cd", + "createdOn": "2023-04-13T14:48:54.709Z", + "lastModifiedOn": "2023-02-03T14:48:54.709Z" + } + ], + "businessPartner": "BPNL00000003CNKC", + "createdOn": "2023-02-03T14:48:54.709Z", + "lastModifiedOn": "2023-02-03T14:48:54.709Z" + } + ] + } + } + + ] + } + ] +} diff --git a/tx-backend/src/test/resources/testdata/importfiles/validImportFile-onlyAsPlannedAsset.json b/tx-backend/src/test/resources/testdata/importfiles/validImportFile-onlyAsPlannedAsset.json new file mode 100644 index 0000000000..83683191eb --- /dev/null +++ b/tx-backend/src/test/resources/testdata/importfiles/validImportFile-onlyAsPlannedAsset.json @@ -0,0 +1,62 @@ +{ + "assets" : [ + { + "assetMetaInfo" : { + "catenaXId" : "urn:uuid:0733946c-59c6-41ae-9570-cb43a6e4eb01" + }, + "submodels" : [ + { + "aspectType" : "urn:bamm:io.catenax.part_as_planned:1.0.1#PartAsPlanned", + "payload" : { + "validityPeriod" : { + "validFrom" : "2019-04-04T03:19:03.000Z", + "validTo" : "2024-12-29T10:25:12.000Z" + }, + "catenaXId" : "urn:uuid:0733946c-59c6-41ae-9570-cb43a6e4eb01", + "partTypeInformation" : { + "manufacturerPartId" : "7805659-25", + "classification" : "product", + "nameAtManufacturer" : "b/test Vehicle Model B" + } + } + }, + { + "aspectType" : "urn:bamm:io.catenax.single_level_bom_as_planned:2.0.0#SingleLevelBomAsPlanned", + "payload" : { + "catenaXId" : "urn:uuid:0733946c-59c6-41ae-9570-cb43a6e4eb01", + "childItems" : [ + { + "validityPeriod" : { + "validFrom" : "2023-03-21T08:17:29.187+01:00", + "validTo" : "2024-07-01T16:10:00.000+01:00" + }, + "quantity" : { + "quantityNumber" : 1, + "measurementUnit" : "unit:piece" + }, + "createdOn" : "2022-09-03T14:48:54.709Z", + "lastModifiedOn" : "2022-02-03T14:48:54.709Z", + "catenaXId" : "urn:uuid:0733946c-59c6-41ae-9570-cb43a6e4da01", + "businessPartner" : "BPNL00000003CML1" + } + ] + } + }, + { + "aspectType" : "urn:bamm:io.catenax.part_site_information_as_planned:1.0.0#PartSiteInformationAsPlanned", + "payload" : { + "catenaXId" : "urn:uuid:0733946c-59c6-41ae-9570-cb43a6e4eb01", + "sites" : [ + { + "functionValidUntil" : "2025-02-08T04:30:48.000Z", + "function" : "production", + "functionValidFrom" : "2019-08-21T02:10:36.000Z", + "catenaXSiteId" : "BPNS000004711DMY" + } + ] + } + } + ] + } + ] +}