124 lines
6.8 KiB
Java
124 lines
6.8 KiB
Java
package com.baiyue.lastleg.controller;
|
|
|
|
import com.baiyue.common.core.api.ApiResponse;
|
|
import com.baiyue.common.core.api.PageResult;
|
|
import com.baiyue.common.event.EventEnvelope;
|
|
import com.baiyue.common.security.AuthenticatedUser;
|
|
import com.baiyue.lastleg.dto.LastlegOrderDetailResponse;
|
|
import com.baiyue.lastleg.dto.LastlegOrderRequests;
|
|
import com.baiyue.lastleg.dto.LastlegOrderSummary;
|
|
import com.baiyue.lastleg.security.InternalServiceTokenGuard;
|
|
import com.baiyue.lastleg.security.OverseasPermissions;
|
|
import com.baiyue.lastleg.service.LastlegOrderService;
|
|
import com.baiyue.lastleg.service.LoadingCompletedConsumer;
|
|
import com.baiyue.lastleg.shipping.service.ContainerShippingNodeConsumer;
|
|
import com.baiyue.common.event.EventTypes;
|
|
import io.swagger.v3.oas.annotations.Operation;
|
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
|
import jakarta.validation.Valid;
|
|
import jakarta.annotation.Resource;
|
|
import org.springframework.http.HttpHeaders;
|
|
import org.springframework.http.HttpStatus;
|
|
import org.springframework.http.MediaType;
|
|
import org.springframework.http.ResponseEntity;
|
|
import org.springframework.security.core.annotation.AuthenticationPrincipal;
|
|
import org.springframework.security.access.prepost.PreAuthorize;
|
|
import org.springframework.web.bind.annotation.GetMapping;
|
|
import org.springframework.web.bind.annotation.PathVariable;
|
|
import org.springframework.web.bind.annotation.PostMapping;
|
|
import org.springframework.web.bind.annotation.PutMapping;
|
|
import org.springframework.web.bind.annotation.RequestBody;
|
|
import org.springframework.web.bind.annotation.RequestHeader;
|
|
import org.springframework.web.bind.annotation.RequestParam;
|
|
import org.springframework.web.bind.annotation.RestController;
|
|
import org.springframework.web.server.ResponseStatusException;
|
|
|
|
import java.nio.charset.StandardCharsets;
|
|
|
|
@RestController
|
|
@Tag(name = "Tail-leg orders")
|
|
public class LastlegOrderController {
|
|
@Resource private LoadingCompletedConsumer consumer;
|
|
@Resource private ContainerShippingNodeConsumer shippingNodeConsumer;
|
|
@Resource private LastlegOrderService orderService;
|
|
@Resource private InternalServiceTokenGuard tokenGuard;
|
|
|
|
@PostMapping("/internal/lastleg/events")
|
|
@Operation(summary = "Receive a first-leg loading or actual shipping-node event",
|
|
description = "Accepts loading-completed V1/V2 and FirstLegContainerShippingNodeRecorded V1 through the internal token boundary; only monotonic actual PICKUP_READY-or-later facts open overseas PDA receiving.")
|
|
public ApiResponse<Integer> receive(
|
|
@RequestHeader(value = "X-Internal-Service-Token", required = false) String token,
|
|
@RequestBody EventEnvelope event) {
|
|
tokenGuard.verify(token);
|
|
int consumed = EventTypes.FIRST_LEG_CONTAINER_SHIPPING_NODE_RECORDED.equals(event.eventType())
|
|
? shippingNodeConsumer.consume(event) : consumer.consume(event);
|
|
return ApiResponse.success(consumed);
|
|
}
|
|
|
|
@GetMapping("/api/platform/v1/last-leg/orders")
|
|
@PreAuthorize("hasAuthority('" + OverseasPermissions.LAST_MILE_ORDER_LIST + "')")
|
|
@Operation(summary = "Page tail-leg order rows", description = "Required authority: " + OverseasPermissions.LAST_MILE_ORDER_LIST)
|
|
public ApiResponse<PageResult<LastlegOrderSummary>> list(
|
|
@AuthenticationPrincipal AuthenticatedUser user,
|
|
@RequestParam(required = false) String customerId,
|
|
@Valid LastlegOrderRequests.Query query) {
|
|
return ApiResponse.success(orderService.page(platformScope(user, customerId), query));
|
|
}
|
|
|
|
@GetMapping("/api/platform/v1/last-leg/orders/{id}")
|
|
@PreAuthorize("hasAuthority('" + OverseasPermissions.LAST_MILE_ORDER_LIST + "')")
|
|
@Operation(summary = "Get one inbound-code-level tail-leg order", description = "Required authority: " + OverseasPermissions.LAST_MILE_ORDER_LIST)
|
|
public ApiResponse<LastlegOrderDetailResponse> detail(
|
|
@AuthenticationPrincipal AuthenticatedUser user,
|
|
@RequestParam(required = false) String customerId,
|
|
@PathVariable long id) {
|
|
return ApiResponse.success(orderService.detail(platformScope(user, customerId), id));
|
|
}
|
|
|
|
@GetMapping(value = "/api/platform/v1/last-leg/orders/export", produces = "text/csv")
|
|
@PreAuthorize("hasAuthority('" + OverseasPermissions.LAST_MILE_ORDER_EXPORT + "')")
|
|
@Operation(summary = "Export filtered tail-leg orders as UTF-8 CSV", description = "Required authority: " + OverseasPermissions.LAST_MILE_ORDER_EXPORT)
|
|
public ResponseEntity<byte[]> export(
|
|
@AuthenticationPrincipal AuthenticatedUser user,
|
|
@RequestParam(required = false) String customerId,
|
|
@Valid LastlegOrderRequests.Query query) {
|
|
byte[] body = orderService.exportCsv(platformScope(user, customerId), query);
|
|
return ResponseEntity.ok()
|
|
.contentType(new MediaType("text", "csv", StandardCharsets.UTF_8))
|
|
.header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=lastleg-orders.csv")
|
|
.body(body);
|
|
}
|
|
|
|
@PutMapping("/api/platform/v1/last-leg/orders/{id}/destination")
|
|
@PreAuthorize("hasAuthority('" + OverseasPermissions.LAST_MILE_ORDER_EDIT + "')")
|
|
@Operation(summary = "Transfer one order to a destination warehouse", description = "Required authority: " + OverseasPermissions.LAST_MILE_ORDER_EDIT)
|
|
public ApiResponse<Integer> transferOne(
|
|
@AuthenticationPrincipal AuthenticatedUser user,
|
|
@RequestParam(required = false) String customerId,
|
|
@PathVariable long id,
|
|
@Valid @RequestBody LastlegOrderRequests.SingleTransferDestination request) {
|
|
return ApiResponse.success(orderService.transferDestination(platformScope(user, customerId), request.withOrderId(id)));
|
|
}
|
|
|
|
@PutMapping("/api/platform/v1/last-leg/orders/destination")
|
|
@PreAuthorize("hasAuthority('" + OverseasPermissions.LAST_MILE_ORDER_EDIT + "')")
|
|
@Operation(summary = "Transfer multiple orders to a destination warehouse", description = "Required authority: " + OverseasPermissions.LAST_MILE_ORDER_EDIT)
|
|
public ApiResponse<Integer> transferBatch(
|
|
@AuthenticationPrincipal AuthenticatedUser user,
|
|
@RequestParam(required = false) String customerId,
|
|
@Valid @RequestBody LastlegOrderRequests.TransferDestination request) {
|
|
return ApiResponse.success(orderService.transferDestination(platformScope(user, customerId), request));
|
|
}
|
|
|
|
private String platformScope(AuthenticatedUser user, String requestedCustomer) {
|
|
if (user == null || user.tenantId() == null) {
|
|
throw new ResponseStatusException(HttpStatus.UNAUTHORIZED);
|
|
}
|
|
if (!"PLATFORM".equals(user.appCode()) || user.tenantId() != 0L) {
|
|
throw new ResponseStatusException(HttpStatus.FORBIDDEN, "Platform identity is required");
|
|
}
|
|
return requestedCustomer == null || requestedCustomer.isBlank() || "0".equals(requestedCustomer)
|
|
? null : requestedCustomer.trim();
|
|
}
|
|
}
|