优化
This commit is contained in:
+2
-1
@@ -22,5 +22,6 @@ public interface DomesticWarehouseDirectoryClient {
|
||||
record Warehouse(Long id, Long tenantId, String warehouseCode, String warehouseName,
|
||||
String warehouseType, String countryCode, String status) { }
|
||||
|
||||
record Address(String stateProvince) { }
|
||||
record Address(String addressType, String countryCode, String stateProvince, String city,
|
||||
String district, String postalCode, String addressLine1, String addressLine2) { }
|
||||
}
|
||||
|
||||
+40
-1
@@ -2,6 +2,7 @@ package com.baiyue.lastleg.dispatch.service;
|
||||
|
||||
import com.baiyue.common.core.api.ResultCode;
|
||||
import com.baiyue.common.core.exception.BizException;
|
||||
import com.baiyue.lastleg.client.DomesticWarehouseDirectoryClient;
|
||||
import com.baiyue.lastleg.client.PrintPdfClient;
|
||||
import com.baiyue.lastleg.dispatch.dto.DispatchResponse;
|
||||
import feign.FeignException;
|
||||
@@ -13,6 +14,7 @@ import java.util.LinkedHashMap;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
@@ -27,6 +29,7 @@ public class DispatchBolPrintService {
|
||||
|
||||
@Resource private DispatchService dispatches;
|
||||
@Resource private PrintPdfClient print;
|
||||
@Resource private DomesticWarehouseDirectoryClient warehouses;
|
||||
@Value("${baiyue.security.internal-service-token:}") private String internalToken;
|
||||
|
||||
public GeneratedPdf generate(String dispatchNo, String requestId) {
|
||||
@@ -52,6 +55,7 @@ public class DispatchBolPrintService {
|
||||
}
|
||||
|
||||
private List<PrintPdfClient.Document> documents(DispatchResponse detail) {
|
||||
String shipFromAddress = warehouseAddress(detail.overseasWarehouseId());
|
||||
Map<String, List<DispatchResponse.BolLine>> groups = new LinkedHashMap<>();
|
||||
for (DispatchResponse.BolLine line : detail.bolLines()) groups.computeIfAbsent(text(line.fbaWarehouseCode()), ignored -> new ArrayList<>()).add(line);
|
||||
List<PrintPdfClient.Document> documents = new ArrayList<>();
|
||||
@@ -67,7 +71,7 @@ public class DispatchBolPrintService {
|
||||
List<PrintPdfClient.CargoRow> rows = lines.subList(offset, end).stream()
|
||||
.map(line -> new PrintPdfClient.CargoRow(text(line.containerNo()), text(line.palletNo()), text(line.fbaWarehouseCode()),
|
||||
text(line.warehouseNo()), text(line.fbaShipmentId()), text(line.poReferenceNo()), line.packageCount())).toList();
|
||||
documents.add(new PrintPdfClient.Document(text(detail.overseasWarehouseName()), "—", text(detail.carrierName()),
|
||||
documents.add(new PrintPdfClient.Document(text(detail.overseasWarehouseName()), shipFromAddress, text(detail.carrierName()),
|
||||
text(detail.fbaAppointmentNo()), dateTime(detail.estimatedArrivalAt()), text(detail.vehiclePlate()), "—",
|
||||
group.getKey(), destination, "—", text(detail.dispatchNo()), unique(lines, true), unique(lines, false),
|
||||
total, page + 1, pages, rows));
|
||||
@@ -77,6 +81,41 @@ public class DispatchBolPrintService {
|
||||
return List.copyOf(documents);
|
||||
}
|
||||
|
||||
private String warehouseAddress(String warehouseId) {
|
||||
long id;
|
||||
try {
|
||||
id = Long.parseLong(warehouseId == null ? "" : warehouseId.strip());
|
||||
} catch (NumberFormatException exception) {
|
||||
throw new BizException(ResultCode.VALIDATION_FAILED, "排车单未关联有效的海外仓");
|
||||
}
|
||||
try {
|
||||
var response = warehouses.activeWarehouse(id, internalToken);
|
||||
if (response == null || !response.successful() || response.data() == null) {
|
||||
throw new BizException(ResultCode.SERVICE_UNAVAILABLE, "仓库主数据暂不可用,无法生成BOL");
|
||||
}
|
||||
List<DomesticWarehouseDirectoryClient.Address> addresses = response.data().addresses();
|
||||
if (addresses == null || addresses.isEmpty()) return "—";
|
||||
DomesticWarehouseDirectoryClient.Address address = addresses.stream().filter(Objects::nonNull)
|
||||
.filter(value -> "OPERATING".equals(value.addressType())).findFirst()
|
||||
.orElseGet(() -> addresses.stream().filter(Objects::nonNull).findFirst().orElse(null));
|
||||
if (address == null) return "—";
|
||||
List<String> parts = new ArrayList<>();
|
||||
add(parts, address.addressLine1());
|
||||
add(parts, address.addressLine2());
|
||||
add(parts, address.city());
|
||||
add(parts, address.stateProvince());
|
||||
add(parts, address.postalCode());
|
||||
add(parts, address.countryCode());
|
||||
return parts.isEmpty() ? "—" : String.join(", ", parts);
|
||||
} catch (FeignException exception) {
|
||||
throw new BizException(ResultCode.SERVICE_UNAVAILABLE, "仓库主数据暂不可用,无法生成BOL");
|
||||
}
|
||||
}
|
||||
|
||||
private void add(List<String> parts, String value) {
|
||||
if (value != null && !value.isBlank()) parts.add(value.strip());
|
||||
}
|
||||
|
||||
static int pageCount(int rowCount) {
|
||||
if (rowCount <= FIRST_PAGE_ROWS) return 1;
|
||||
return 1 + (rowCount - FIRST_PAGE_ROWS + CONTINUATION_PAGE_ROWS - 1) / CONTINUATION_PAGE_ROWS;
|
||||
|
||||
+2
-1
@@ -33,6 +33,7 @@ class DomesticWarehouseDirectoryClientContractTest {
|
||||
"warehouseType:String", "countryCode:String", "status:String");
|
||||
assertThat(Arrays.stream(DomesticWarehouseDirectoryClient.Address.class.getRecordComponents())
|
||||
.map(value -> value.getName() + ":" + value.getType().getSimpleName()))
|
||||
.containsExactly("stateProvince:String");
|
||||
.containsExactly("addressType:String", "countryCode:String", "stateProvince:String", "city:String",
|
||||
"district:String", "postalCode:String", "addressLine1:String", "addressLine2:String");
|
||||
}
|
||||
}
|
||||
|
||||
+60
@@ -1,10 +1,41 @@
|
||||
package com.baiyue.lastleg.dispatch.service;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import com.baiyue.common.core.api.ApiResponse;
|
||||
import com.baiyue.lastleg.client.DomesticWarehouseDirectoryClient;
|
||||
import com.baiyue.lastleg.client.PrintPdfClient;
|
||||
import com.baiyue.lastleg.dispatch.dto.DispatchResponse;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.test.util.ReflectionTestUtils;
|
||||
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
class DispatchBolPrintServiceTest {
|
||||
@Mock private DispatchService dispatches;
|
||||
@Mock private PrintPdfClient print;
|
||||
@Mock private DomesticWarehouseDirectoryClient warehouses;
|
||||
@InjectMocks private DispatchBolPrintService service;
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
ReflectionTestUtils.setField(service, "internalToken", "internal-test-token");
|
||||
}
|
||||
|
||||
@Test
|
||||
void usesDenseFirstAndContinuationPageCapacities() {
|
||||
assertThat(DispatchBolPrintService.pageCount(1)).isEqualTo(1);
|
||||
@@ -15,4 +46,33 @@ class DispatchBolPrintServiceTest {
|
||||
assertThat(DispatchBolPrintService.pageCount(70)).isEqualTo(3);
|
||||
assertThat(DispatchBolPrintService.pageCount(71)).isEqualTo(4);
|
||||
}
|
||||
|
||||
@Test
|
||||
void resolvesTheOperatingWarehouseAddressIntoTheBolRequest() {
|
||||
String warehouseId = "193000000000200003";
|
||||
DispatchResponse detail = new DispatchResponse(1L, "DS-WH-20260911-624449", "DEV-23653906",
|
||||
null, null, "五月开发验收车队", null, null, warehouseId, "洛杉矶仓", null,
|
||||
null, null, null, LocalDateTime.of(2026, 9, 12, 2, 40, 20), "PENDING_DEPARTURE",
|
||||
1, 1, 1, 0, 0, 1, null, LocalDateTime.of(2026, 9, 11, 10, 0), List.of(),
|
||||
List.of(new DispatchResponse.BolLine("TSTU3539519", "DP-260911-0027", "ABE2", "ABE2",
|
||||
"NYEXX2609110214", null, null, 1)));
|
||||
var address = new DomesticWarehouseDirectoryClient.Address("OPERATING", "US", "CA", "Los Angeles",
|
||||
null, "90001", "Los Angeles warehouse generic address pending maintenance", null);
|
||||
var warehouse = new DomesticWarehouseDirectoryClient.Warehouse(Long.parseLong(warehouseId), 0L,
|
||||
"US-LAX", "洛杉矶仓", "OVERSEAS", "US", "ACTIVE");
|
||||
when(dispatches.platformDetail(detail.dispatchNo())).thenReturn(detail);
|
||||
when(warehouses.activeWarehouse(Long.parseLong(warehouseId), "internal-test-token"))
|
||||
.thenReturn(ApiResponse.success(new DomesticWarehouseDirectoryClient.Detail(warehouse, List.of(address))));
|
||||
when(print.generateDispatchBol(eq("internal-test-token"), eq("request-1"), any()))
|
||||
.thenReturn(ResponseEntity.ok().contentType(MediaType.APPLICATION_PDF)
|
||||
.header("X-Print-Page-Count", "1").body("%PDF-".getBytes(StandardCharsets.US_ASCII)));
|
||||
|
||||
service.generate(detail.dispatchNo(), "request-1");
|
||||
|
||||
ArgumentCaptor<PrintPdfClient.Request> request = ArgumentCaptor.forClass(PrintPdfClient.Request.class);
|
||||
verify(print).generateDispatchBol(eq("internal-test-token"), eq("request-1"), request.capture());
|
||||
assertThat(request.getValue().documents()).singleElement().satisfies(document ->
|
||||
assertThat(document.shipFromAddress()).isEqualTo(
|
||||
"Los Angeles warehouse generic address pending maintenance, Los Angeles, CA, 90001, US"));
|
||||
}
|
||||
}
|
||||
|
||||
+2
-1
@@ -91,7 +91,8 @@ class FbaWarehouseValidatorTest {
|
||||
return new DomesticWarehouseDirectoryClient.Detail(
|
||||
new DomesticWarehouseDirectoryClient.Warehouse(193000000000000001L, 0L, code, name,
|
||||
type, "US", status),
|
||||
List.of(new DomesticWarehouseDirectoryClient.Address("CA")));
|
||||
List.of(new DomesticWarehouseDirectoryClient.Address("OPERATING", "US", "CA", "Los Angeles",
|
||||
null, "90001", "123 Logistics Ave", null)));
|
||||
}
|
||||
|
||||
private void assertInvalid(org.assertj.core.api.ThrowableAssert.ThrowingCallable action) {
|
||||
|
||||
Reference in New Issue
Block a user