Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat: ERP Adapter response interface #418

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.eclipse.tractusx.puris.backend.common.util.VariablesService;
import org.eclipse.tractusx.puris.backend.erpadapter.domain.model.ErpAdapterRequest;
import org.eclipse.tractusx.puris.backend.erpadapter.logic.service.ErpAdapterRequestService;
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;
Expand All @@ -37,6 +39,7 @@
import org.eclipse.tractusx.puris.backend.stock.domain.model.ReportedMaterialItemStock;
import org.eclipse.tractusx.puris.backend.stock.domain.model.ReportedProductItemStock;
import org.eclipse.tractusx.puris.backend.common.domain.model.measurement.ItemUnitEnumeration;
import org.eclipse.tractusx.puris.backend.stock.logic.dto.itemstocksamm.DirectionCharacteristic;
import org.eclipse.tractusx.puris.backend.stock.logic.service.MaterialItemStockService;
import org.eclipse.tractusx.puris.backend.stock.logic.service.ProductItemStockService;
import org.eclipse.tractusx.puris.backend.stock.logic.service.ReportedMaterialItemStockService;
Expand Down Expand Up @@ -76,6 +79,9 @@ public class DataInjectionCommandLineRunner implements CommandLineRunner {
@Autowired
private VariablesService variablesService;

@Autowired
private ErpAdapterRequestService erpAdapterRequestService;

private ObjectMapper objectMapper;

private final String semiconductorMatNbrCustomer = "MNR-7307-AU340474.002";
Expand Down Expand Up @@ -241,6 +247,19 @@ private void setupCustomerRole() throws JsonProcessingException {
.locationBpna(supplierPartner.getSites().first().getAddresses().first().getBpna())
.build();
reportedProductItemStockService.create(reportedProductItemStock);

// TODO: remove mock
ErpAdapterRequest mockRequest = ErpAdapterRequest
.builder()
.partnerBpnl(supplierPartner.getBpnl())
.requestDate(new Date(System.currentTimeMillis()-3*60*60*1000))
.ownMaterialNumber(semiconductorMaterial.getOwnMaterialNumber())
.directionCharacteristic(DirectionCharacteristic.INBOUND)
.requestType("ItemStock")
.sammVersion("2.0")
.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 @@ -83,7 +83,20 @@ public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
.authorizeHttpRequests(
// any request in spring context
(authorizeHttpRequests) -> authorizeHttpRequests
.requestMatchers("/stockView/**", "/partners/**", "/materials/**", "/materialpartnerrelations/**", "/item-stock/**", "/production/**", "/delivery/**", "/demand/**", "/planned-production/**", "/material-demand/**", "/delivery-information/**", "/edc/**", "/parttypeinformation/**")
.requestMatchers("/stockView/**",
"/partners/**",
"/materials/**",
"/materialpartnerrelations/**",
"/item-stock/**",
"/production/**",
"/delivery/**",
"/demand/**",
"/planned-production/**",
"/material-demand/**",
"/delivery-information/**",
"/edc/**",
"/erp-adapter/**",
"/parttypeinformation/**")
.authenticated()
.requestMatchers("/swagger-ui/**", "/v3/api-docs/**", "/health/**").permitAll()
.dispatcherTypeMatchers(DispatcherType.ERROR).permitAll()
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
/*
* 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.controller;

import com.fasterxml.jackson.databind.JsonNode;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.ExampleObject;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.responses.ApiResponses;
import lombok.extern.slf4j.Slf4j;
import org.eclipse.tractusx.puris.backend.erpadapter.logic.service.ItemStockErpAdapterService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.util.Date;
import java.util.UUID;

import static org.eclipse.tractusx.puris.backend.common.util.PatternStore.BPNL_PATTERN;
import static org.eclipse.tractusx.puris.backend.common.util.PatternStore.NON_EMPTY_NON_VERTICAL_WHITESPACE_PATTERN;

@RestController
@RequestMapping("erp-adapter")
@Slf4j
public class ErpAdapterController {

@Autowired
private ItemStockErpAdapterService itemStockErpAdapterService;

@Operation(description = "This endpoint accepts responses from the ERP adapter. Incoming messages are expected to " +
"carry a SAMM of the previously requested type. \n\nPlease note that this version currently accepts multiple responses " +
"addressing the same request-id for testing purposes. However, in the near future, this will be enforced strictly. " +
"I.e. only the first response for a given request-id will be accepted. All later responses addressing the same request-id" +
" will be rejected (status code 409)\n\n" +
"Currently supported: \n\n" +
"| response-type | samm-version |\n" +
"|---------------|--------------|\n" +
"| ItemStock | 2.0 |"
)
@ApiResponses(value = {
@ApiResponse(responseCode = "201", description = "accepted"),
@ApiResponse(responseCode = "400", description = "bad request"),
@ApiResponse(responseCode = "404", description = "unknown request-id"),
@ApiResponse(responseCode = "409", description = "repeated answer for request-id"),
@ApiResponse(responseCode = "500", description = "internal server error"),
@ApiResponse(responseCode = "501", description = "unsupported response-type")
})
@PutMapping
public ResponseEntity<?> putMethod(
@RequestParam("request-id") UUID requestId,
@RequestParam("bpnl") String partnerBpnl,
@RequestParam("response-type") String responseType,
@RequestParam("samm-version") String sammVersion,
@RequestParam(value = "response-timestamp")
@Parameter(example = "2024-05-28T15:00:00")
@DateTimeFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss") Date responseTimestamp,
@io.swagger.v3.oas.annotations.parameters.RequestBody(content = {@Content(examples = {
@ExampleObject(itemStock20Sample)
})})
@RequestBody JsonNode requestBody
) {
boolean valid = BPNL_PATTERN.matcher(partnerBpnl).matches();
valid = valid && NON_EMPTY_NON_VERTICAL_WHITESPACE_PATTERN.matcher(responseType).matches();
valid = valid && NON_EMPTY_NON_VERTICAL_WHITESPACE_PATTERN.matcher(sammVersion).matches();
if (!valid) {
return ResponseEntity.badRequest().build();
}
Dto dto = new Dto(requestId, partnerBpnl, responseType, sammVersion, responseTimestamp, requestBody);
int responseCode = 501;
switch (responseType) {
case "ItemStock" -> responseCode = itemStockErpAdapterService.receiveItemStockUpdate(dto);
default -> {
return ResponseEntity.status(responseCode).body("Unsupported response type: " + responseType);
}
}
return ResponseEntity.status(responseCode).build();
}

public record Dto(UUID requestId, String partnerBpnl, String responseType, String sammVersion,
Date responseTimeStamp, JsonNode body){}

private final static String itemStock20Sample = "{\n" +
" \"materialGlobalAssetId\": null,\n" +
" \"positions\": [\n" +
" {\n" +
" \"orderPositionReference\": {\n" +
" \"supplierOrderId\": \"M-Nbr-4711\",\n" +
" \"customerOrderId\": \"C-Nbr-4711\",\n" +
" \"customerOrderPositionId\": \"PositionId-01\"\n" +
" },\n" +
" \"allocatedStocks\": [\n" +
" {\n" +
" \"isBlocked\": false,\n" +
" \"stockLocationBPNA\": \"BPNA4444444444AA\",\n" +
" \"lastUpdatedOnDateTime\": \"2023-04-28T14:23:00.123456+14:00\",\n" +
" \"quantityOnAllocatedStock\": {\n" +
" \"value\": 22.0,\n" +
" \"unit\": \"unit:piece\"\n" +
" },\n" +
" \"stockLocationBPNS\": \"BPNS4444444444XX\"\n" +
" }\n" +
" ]\n" +
" },\n" +
" {\n" +
" \"orderPositionReference\": {\n" +
" \"supplierOrderId\": \"M-Nbr-4711\",\n" +
" \"customerOrderId\": \"C-Nbr-4711\",\n" +
" \"customerOrderPositionId\": \"PositionId-03\"\n" +
" },\n" +
" \"allocatedStocks\": [\n" +
" {\n" +
" \"isBlocked\": false,\n" +
" \"stockLocationBPNA\": \"BPNA4444444444AA\",\n" +
" \"lastUpdatedOnDateTime\": \"2023-04-28T14:23:00.123456+14:00\",\n" +
" \"quantityOnAllocatedStock\": {\n" +
" \"value\": 66.0,\n" +
" \"unit\": \"unit:piece\"\n" +
" },\n" +
" \"stockLocationBPNS\": \"BPNS4444444444XX\"\n" +
" }\n" +
" ]\n" +
" },\n" +
" {\n" +
" \"orderPositionReference\": {\n" +
" \"supplierOrderId\": \"M-Nbr-4711\",\n" +
" \"customerOrderId\": \"C-Nbr-4711\",\n" +
" \"customerOrderPositionId\": \"PositionId-02\"\n" +
" },\n" +
" \"allocatedStocks\": [\n" +
" {\n" +
" \"isBlocked\": true,\n" +
" \"stockLocationBPNA\": \"BPNA4444444444AA\",\n" +
" \"lastUpdatedOnDateTime\": \"2023-04-28T14:23:00.123456+14:00\",\n" +
" \"quantityOnAllocatedStock\": {\n" +
" \"value\": 44.0,\n" +
" \"unit\": \"unit:piece\"\n" +
" },\n" +
" \"stockLocationBPNS\": \"BPNS4444444444XX\"\n" +
" }\n" +
" ]\n" +
" }\n" +
" ],\n" +
" \"direction\": \"INBOUND\"\n" +
"}";
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
/*
* 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.domain.model;

import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.Id;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Pattern;
import lombok.*;
import org.eclipse.tractusx.puris.backend.common.util.PatternStore;
import org.eclipse.tractusx.puris.backend.stock.logic.dto.itemstocksamm.DirectionCharacteristic;

import java.util.Date;
import java.util.UUID;

@Entity
@Getter
@Setter
@Builder
@AllArgsConstructor
@NoArgsConstructor
@ToString
public class ErpAdapterRequest {
@GeneratedValue
@Id
private UUID id;

@Pattern(regexp = PatternStore.BPNL_STRING)
@NotNull
private String partnerBpnl;

@Pattern(regexp = PatternStore.NON_EMPTY_NON_VERTICAL_WHITESPACE_STRING)
@NotNull
private String requestType;

@Pattern(regexp = PatternStore.NON_EMPTY_NON_VERTICAL_WHITESPACE_STRING)
@NotNull
private String sammVersion;

@NotNull
private Date requestDate;

private Date responseReceivedDate;

@Pattern(regexp = PatternStore.NON_EMPTY_NON_VERTICAL_WHITESPACE_STRING)
@NotNull
private String ownMaterialNumber;

private DirectionCharacteristic directionCharacteristic;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/*
* 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.domain.repository;

import org.eclipse.tractusx.puris.backend.erpadapter.domain.model.ErpAdapterRequest;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

import java.util.UUID;

@Repository
public interface ErpAdapterRequestRepository extends JpaRepository<ErpAdapterRequest, UUID> {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
/*
* 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 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
public class ErpAdapterRequestService {

@Autowired
private ErpAdapterRequestRepository repository;

public ErpAdapterRequest create(ErpAdapterRequest erpAdapterRequest) {
if (erpAdapterRequest.getId() != null && repository.existsById(erpAdapterRequest.getId())) {
return null;
}
return repository.save(erpAdapterRequest);
}

public ErpAdapterRequest get(UUID id) {
// TODO: Remove when mock is removed
return repository.findById(id).orElse(repository.findAll().getFirst());
// return repository.findById(id).orElse(null);
}

public ErpAdapterRequest update(ErpAdapterRequest erpAdapterRequest) {
if (repository.existsById(erpAdapterRequest.getId())) {
return repository.save(erpAdapterRequest);
}
return null;
}

public void delete(UUID id) {
repository.deleteById(id);
}
}
Loading
Loading