fix(firstleg): make scanned shipment id optional
This commit is contained in:
@@ -19,7 +19,7 @@ public final class MojiaMeasurementDtos {
|
|||||||
public record UploadRequest(
|
public record UploadRequest(
|
||||||
@NotBlank @Size(max = 128) String boxCode,
|
@NotBlank @Size(max = 128) String boxCode,
|
||||||
@JsonProperty("shipment_id") @JsonAlias("shipmentId")
|
@JsonProperty("shipment_id") @JsonAlias("shipmentId")
|
||||||
@NotBlank @Size(max = 64) String shipmentId,
|
@Size(max = 64) String shipmentId,
|
||||||
@NotNull @DecimalMin("0.001") @DecimalMax("999999999.999") BigDecimal length,
|
@NotNull @DecimalMin("0.001") @DecimalMax("999999999.999") BigDecimal length,
|
||||||
@NotNull @DecimalMin("0.001") @DecimalMax("999999999.999") BigDecimal width,
|
@NotNull @DecimalMin("0.001") @DecimalMax("999999999.999") BigDecimal width,
|
||||||
@NotNull @DecimalMin("0.001") @DecimalMax("999999999.999") BigDecimal height,
|
@NotNull @DecimalMin("0.001") @DecimalMax("999999999.999") BigDecimal height,
|
||||||
|
|||||||
+6
-2
@@ -79,7 +79,7 @@ public class MojiaMeasurementOpenApiService {
|
|||||||
app.tenantId(), app.subjectId(), new CartonMeasurementCommand(
|
app.tenantId(), app.subjectId(), new CartonMeasurementCommand(
|
||||||
request.boxCode(), request.length(), request.width(), request.height(), request.weight(),
|
request.boxCode(), request.length(), request.width(), request.height(), request.weight(),
|
||||||
request.machineNo(), request.measuredAt() == null ? LocalDateTime.now() : request.measuredAt(),
|
request.machineNo(), request.measuredAt() == null ? LocalDateTime.now() : request.measuredAt(),
|
||||||
image, request.shipmentId().trim()));
|
image, optionalTrim(request.shipmentId())));
|
||||||
} catch (BizException exception) {
|
} catch (BizException exception) {
|
||||||
if (exception.getResultCode() == ResultCode.NOT_FOUND) {
|
if (exception.getResultCode() == ResultCode.NOT_FOUND) {
|
||||||
return saveUnmatched(app, request, image, exception);
|
return saveUnmatched(app, request, image, exception);
|
||||||
@@ -117,7 +117,7 @@ public class MojiaMeasurementOpenApiService {
|
|||||||
receipt.setTenantId(app.tenantId());
|
receipt.setTenantId(app.tenantId());
|
||||||
receipt.setSubjectId(app.subjectId());
|
receipt.setSubjectId(app.subjectId());
|
||||||
receipt.setBoxCode(request.boxCode().trim());
|
receipt.setBoxCode(request.boxCode().trim());
|
||||||
receipt.setScannedShipmentId(request.shipmentId().trim());
|
receipt.setScannedShipmentId(optionalTrim(request.shipmentId()));
|
||||||
receipt.setLengthCm(request.length());
|
receipt.setLengthCm(request.length());
|
||||||
receipt.setWidthCm(request.width());
|
receipt.setWidthCm(request.width());
|
||||||
receipt.setHeightCm(request.height());
|
receipt.setHeightCm(request.height());
|
||||||
@@ -218,6 +218,10 @@ public class MojiaMeasurementOpenApiService {
|
|||||||
return normalized.length() <= 160 ? normalized : normalized.substring(0, 160);
|
return normalized.length() <= 160 ? normalized : normalized.substring(0, 160);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private String optionalTrim(String value) {
|
||||||
|
return value == null || value.isBlank() ? null : value.trim();
|
||||||
|
}
|
||||||
|
|
||||||
private record InMemoryMultipartFile(byte[] content) implements MultipartFile {
|
private record InMemoryMultipartFile(byte[] content) implements MultipartFile {
|
||||||
@Override public String getName() { return "image"; }
|
@Override public String getName() { return "image"; }
|
||||||
@Override public String getOriginalFilename() { return "mojia-measurement.jpg"; }
|
@Override public String getOriginalFilename() { return "mojia-measurement.jpg"; }
|
||||||
|
|||||||
@@ -239,10 +239,10 @@ paths:
|
|||||||
application/json:
|
application/json:
|
||||||
schema:
|
schema:
|
||||||
type: object
|
type: object
|
||||||
required: [boxCode, shipment_id, length, width, height, machineNo, picture]
|
required: [boxCode, length, width, height, machineNo, picture]
|
||||||
properties:
|
properties:
|
||||||
boxCode: {type: string, maxLength: 128, example: 'RK-2085911321565003778#4-1'}
|
boxCode: {type: string, maxLength: 128, example: 'RK-2085911321565003778#4-1'}
|
||||||
shipment_id: {type: string, maxLength: 64, example: 'FBA19L5KMY2CU000002', description: '设备从Amazon FBA箱标实际扫描得到;系统只保存,不生成且不覆盖客户下单值'}
|
shipment_id: {type: string, maxLength: 64, example: 'FBA19L5KMY2CU000002', description: '可选;设备从Amazon FBA箱标实际扫描得到,有则原样上传;系统只保存,不生成且不覆盖客户下单值'}
|
||||||
length: {type: number, format: decimal, minimum: 0.001}
|
length: {type: number, format: decimal, minimum: 0.001}
|
||||||
width: {type: number, format: decimal, minimum: 0.001}
|
width: {type: number, format: decimal, minimum: 0.001}
|
||||||
height: {type: number, format: decimal, minimum: 0.001}
|
height: {type: number, format: decimal, minimum: 0.001}
|
||||||
|
|||||||
+2
-1
@@ -57,7 +57,8 @@ class OpenApiInboundMeasurementControllerContractTest {
|
|||||||
.contains("Nonce")
|
.contains("Nonce")
|
||||||
.contains("inboundDetailId")
|
.contains("inboundDetailId")
|
||||||
.contains("multipart/form-data")
|
.contains("multipart/form-data")
|
||||||
.contains("required: [boxCode, shipment_id, length, width, height, machineNo, picture]")
|
.contains("required: [boxCode, length, width, height, machineNo, picture]")
|
||||||
|
.doesNotContain("required: [boxCode, shipment_id")
|
||||||
.contains("shipment_id:")
|
.contains("shipment_id:")
|
||||||
.contains("不改变入库单状态");
|
.contains("不改变入库单状态");
|
||||||
}
|
}
|
||||||
|
|||||||
+9
-8
@@ -22,7 +22,6 @@ import org.springframework.test.util.ReflectionTestUtils;
|
|||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
import static org.mockito.ArgumentMatchers.any;
|
import static org.mockito.ArgumentMatchers.any;
|
||||||
@@ -33,7 +32,7 @@ import static org.mockito.Mockito.when;
|
|||||||
|
|
||||||
class MojiaMeasurementOpenApiServiceTest {
|
class MojiaMeasurementOpenApiServiceTest {
|
||||||
@Test
|
@Test
|
||||||
void shipmentIdIsRequiredAndCamelCaseAliasIsAccepted() throws Exception {
|
void shipmentIdIsOptionalAndCamelCaseAliasIsAccepted() throws Exception {
|
||||||
ObjectMapper mapper = new ObjectMapper().findAndRegisterModules();
|
ObjectMapper mapper = new ObjectMapper().findAndRegisterModules();
|
||||||
var validator = Validation.buildDefaultValidatorFactory().getValidator();
|
var validator = Validation.buildDefaultValidatorFactory().getValidator();
|
||||||
|
|
||||||
@@ -41,12 +40,13 @@ class MojiaMeasurementOpenApiServiceTest {
|
|||||||
json().replace("\"shipment_id\"", "\"shipmentId\""), UploadRequest.class);
|
json().replace("\"shipment_id\"", "\"shipmentId\""), UploadRequest.class);
|
||||||
UploadRequest missing = mapper.readValue(
|
UploadRequest missing = mapper.readValue(
|
||||||
json().replace("\"shipment_id\":\"FBA19L5KMY2CU000002\",", ""), UploadRequest.class);
|
json().replace("\"shipment_id\":\"FBA19L5KMY2CU000002\",", ""), UploadRequest.class);
|
||||||
|
UploadRequest blank = mapper.readValue(
|
||||||
|
json().replace("FBA19L5KMY2CU000002", ""), UploadRequest.class);
|
||||||
|
|
||||||
assertThat(camelCase.shipmentId()).isEqualTo("FBA19L5KMY2CU000002");
|
assertThat(camelCase.shipmentId()).isEqualTo("FBA19L5KMY2CU000002");
|
||||||
assertThat(validator.validate(camelCase)).isEmpty();
|
assertThat(validator.validate(camelCase)).isEmpty();
|
||||||
assertThat(validator.validate(missing).stream()
|
assertThat(validator.validate(missing)).isEmpty();
|
||||||
.map(violation -> violation.getPropertyPath().toString()).collect(java.util.stream.Collectors.toSet()))
|
assertThat(validator.validate(blank)).isEmpty();
|
||||||
.isEqualTo(Set.of("shipmentId"));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -90,15 +90,16 @@ class MojiaMeasurementOpenApiServiceTest {
|
|||||||
images, receipts);
|
images, receipts);
|
||||||
ReflectionTestUtils.setField(service, "internalToken", "internal-token");
|
ReflectionTestUtils.setField(service, "internalToken", "internal-token");
|
||||||
MeasurementRequestHeaders headers = new MeasurementRequestHeaders("mojia", null, null, null, null);
|
MeasurementRequestHeaders headers = new MeasurementRequestHeaders("mojia", null, null, null, null);
|
||||||
|
String requestJson = json().replace("\"shipment_id\":\"FBA19L5KMY2CU000002\",", "");
|
||||||
when(authenticator.authenticate("POST", MojiaMeasurementOpenApiService.CALLBACK_PATH,
|
when(authenticator.authenticate("POST", MojiaMeasurementOpenApiService.CALLBACK_PATH,
|
||||||
headers, json(), false)).thenReturn(new AuthenticatedMeasurementApp("mojia", 10001L, 90001L, Map.of()));
|
headers, requestJson, false)).thenReturn(new AuthenticatedMeasurementApp("mojia", 10001L, 90001L, Map.of()));
|
||||||
when(cartons.upsert(eq(10001L), eq(90001L), any()))
|
when(cartons.upsert(eq(10001L), eq(90001L), any()))
|
||||||
.thenThrow(new BizException(ResultCode.NOT_FOUND, "箱号不存在或不属于当前客户"));
|
.thenThrow(new BizException(ResultCode.NOT_FOUND, "箱号不存在或不属于当前客户"));
|
||||||
when(images.uploadReceipt(eq("internal-token"), eq(90001L), eq(10001L), any(Long.TYPE), any()))
|
when(images.uploadReceipt(eq("internal-token"), eq(90001L), eq(10001L), any(Long.TYPE), any()))
|
||||||
.thenReturn(ApiResponse.success(new MeasurementImageClient.UploadResult(
|
.thenReturn(ApiResponse.success(new MeasurementImageClient.UploadResult(
|
||||||
3L, "mojia.jpg", "image/jpeg", 4L, "NOT_REQUIRED", null, null, null, null)));
|
3L, "mojia.jpg", "image/jpeg", 4L, "NOT_REQUIRED", null, null, null, null)));
|
||||||
|
|
||||||
UploadResponse result = service.receive(headers, json());
|
UploadResponse result = service.receive(headers, requestJson);
|
||||||
|
|
||||||
assertThat(result.accepted()).isTrue();
|
assertThat(result.accepted()).isTrue();
|
||||||
assertThat(result.matched()).isFalse();
|
assertThat(result.matched()).isFalse();
|
||||||
@@ -108,7 +109,7 @@ class MojiaMeasurementOpenApiServiceTest {
|
|||||||
ArgumentCaptor.forClass(MojiaMeasurementReceiptEntity.class);
|
ArgumentCaptor.forClass(MojiaMeasurementReceiptEntity.class);
|
||||||
verify(receipts).insert(receipt.capture());
|
verify(receipts).insert(receipt.capture());
|
||||||
assertThat(receipt.getValue().getBoxCode()).isEqualTo("RK-001#4-1");
|
assertThat(receipt.getValue().getBoxCode()).isEqualTo("RK-001#4-1");
|
||||||
assertThat(receipt.getValue().getScannedShipmentId()).isEqualTo("FBA19L5KMY2CU000002");
|
assertThat(receipt.getValue().getScannedShipmentId()).isNull();
|
||||||
assertThat(receipt.getValue().getLengthCm()).isEqualByComparingTo("60.1");
|
assertThat(receipt.getValue().getLengthCm()).isEqualByComparingTo("60.1");
|
||||||
assertThat(receipt.getValue().getImageFileId()).isEqualTo(3L);
|
assertThat(receipt.getValue().getImageFileId()).isEqualTo(3L);
|
||||||
assertThat(receipt.getValue().getStatus()).isEqualTo("UNMATCHED");
|
assertThat(receipt.getValue().getStatus()).isEqualTo("UNMATCHED");
|
||||||
|
|||||||
Reference in New Issue
Block a user