Files
baiyue-firstleg/lastleg-service/src/main/java/com/baiyue/lastleg/controller/LastlegOrderController.java
T

119 lines
6.5 KiB
Java
Raw Normal View History

2026-08-19 16:24:02 +08:00
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;
2026-08-20 18:02:38 +08:00
import com.baiyue.lastleg.security.OverseasPermissions;
2026-08-19 16:24:02 +08:00
import com.baiyue.lastleg.service.LastlegOrderService;
import com.baiyue.lastleg.service.LoadingCompletedConsumer;
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;
2026-08-20 18:02:38 +08:00
import org.springframework.security.access.prepost.PreAuthorize;
2026-08-19 16:24:02 +08:00
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 LastlegOrderService orderService;
@Resource private InternalServiceTokenGuard tokenGuard;
@PostMapping("/internal/lastleg/events")
2026-08-24 17:15:48 +08:00
@Operation(summary = "Receive a first-leg loading-completed event",
description = "V2 orders[].destinationType is FBA or OVERSEAS. FBA may use package counts; OVERSEAS requires one carton mark per loaded package. Legacy events are accepted only when the destination type can be inferred safely.")
2026-08-19 16:24:02 +08:00
public ApiResponse<Integer> receive(
@RequestHeader(value = "X-Internal-Service-Token", required = false) String token,
@RequestBody EventEnvelope event) {
tokenGuard.verify(token);
return ApiResponse.success(consumer.consume(event));
}
@GetMapping("/api/platform/v1/last-leg/orders")
2026-08-20 18:02:38 +08:00
@PreAuthorize("hasAuthority('" + OverseasPermissions.LAST_MILE_ORDER_LIST + "')")
@Operation(summary = "Page tail-leg order rows", description = "Required authority: " + OverseasPermissions.LAST_MILE_ORDER_LIST)
2026-08-19 16:24:02 +08:00
public ApiResponse<PageResult<LastlegOrderSummary>> list(
@AuthenticationPrincipal AuthenticatedUser user,
@RequestParam(required = false) String customerId,
@Valid LastlegOrderRequests.Query query) {
2026-08-21 10:43:25 +08:00
return ApiResponse.success(orderService.page(platformScope(user, customerId), query));
2026-08-19 16:24:02 +08:00
}
@GetMapping("/api/platform/v1/last-leg/orders/{id}")
2026-08-20 18:02:38 +08:00
@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)
2026-08-19 16:24:02 +08:00
public ApiResponse<LastlegOrderDetailResponse> detail(
@AuthenticationPrincipal AuthenticatedUser user,
@RequestParam(required = false) String customerId,
@PathVariable long id) {
2026-08-21 10:43:25 +08:00
return ApiResponse.success(orderService.detail(platformScope(user, customerId), id));
2026-08-19 16:24:02 +08:00
}
@GetMapping(value = "/api/platform/v1/last-leg/orders/export", produces = "text/csv")
2026-08-20 18:02:38 +08:00
@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)
2026-08-19 16:24:02 +08:00
public ResponseEntity<byte[]> export(
@AuthenticationPrincipal AuthenticatedUser user,
@RequestParam(required = false) String customerId,
@Valid LastlegOrderRequests.Query query) {
2026-08-21 10:43:25 +08:00
byte[] body = orderService.exportCsv(platformScope(user, customerId), query);
2026-08-19 16:24:02 +08:00
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")
2026-08-20 18:02:38 +08:00
@PreAuthorize("hasAuthority('" + OverseasPermissions.LAST_MILE_ORDER_EDIT + "')")
@Operation(summary = "Transfer one order to a destination warehouse", description = "Required authority: " + OverseasPermissions.LAST_MILE_ORDER_EDIT)
2026-08-19 16:24:02 +08:00
public ApiResponse<Integer> transferOne(
@AuthenticationPrincipal AuthenticatedUser user,
@RequestParam(required = false) String customerId,
@PathVariable long id,
@Valid @RequestBody LastlegOrderRequests.SingleTransferDestination request) {
2026-08-21 10:43:25 +08:00
return ApiResponse.success(orderService.transferDestination(platformScope(user, customerId), request.withOrderId(id)));
2026-08-19 16:24:02 +08:00
}
@PutMapping("/api/platform/v1/last-leg/orders/destination")
2026-08-20 18:02:38 +08:00
@PreAuthorize("hasAuthority('" + OverseasPermissions.LAST_MILE_ORDER_EDIT + "')")
@Operation(summary = "Transfer multiple orders to a destination warehouse", description = "Required authority: " + OverseasPermissions.LAST_MILE_ORDER_EDIT)
2026-08-19 16:24:02 +08:00
public ApiResponse<Integer> transferBatch(
@AuthenticationPrincipal AuthenticatedUser user,
@RequestParam(required = false) String customerId,
@Valid @RequestBody LastlegOrderRequests.TransferDestination request) {
2026-08-21 10:43:25 +08:00
return ApiResponse.success(orderService.transferDestination(platformScope(user, customerId), request));
2026-08-19 16:24:02 +08:00
}
2026-08-21 10:43:25 +08:00
private String platformScope(AuthenticatedUser user, String requestedCustomer) {
2026-08-19 16:24:02 +08:00
if (user == null || user.tenantId() == null) {
throw new ResponseStatusException(HttpStatus.UNAUTHORIZED);
}
2026-08-21 10:43:25 +08:00
if (!"PLATFORM".equals(user.appCode()) || user.tenantId() != 0L) {
throw new ResponseStatusException(HttpStatus.FORBIDDEN, "Platform identity is required");
2026-08-19 16:24:02 +08:00
}
2026-08-21 10:43:25 +08:00
return requestedCustomer == null || requestedCustomer.isBlank() || "0".equals(requestedCustomer)
? null : requestedCustomer.trim();
2026-08-19 16:24:02 +08:00
}
}