This commit is contained in:
2026-08-08 10:11:04 +08:00
parent f3c2bafec8
commit fc14856ea3
64 changed files with 50932 additions and 30 deletions
@@ -1,6 +1,7 @@
package com.baiyue.order.service;
import com.baiyue.common.core.api.PageResult;
import com.baiyue.common.core.api.ResultCode;
import com.baiyue.common.core.exception.BizException;
import com.baiyue.order.dto.OrderDetailResponse;
import com.baiyue.order.dto.OrderRequests;
@@ -87,7 +88,7 @@ public class OrderApplicationService {
OrderStatus before = order.getStatus();
if (before != OrderStatus.DRAFT && before != OrderStatus.REJECTED
&& !(allowSubmitted && before == OrderStatus.SUBMITTED)) {
throw new BizException("当前订单状态不允许编辑订单资料");
throw new BizException(ResultCode.CONFLICT, "当前订单状态不允许编辑订单资料");
}
pricingChannelGuard.requireAvailable(tenantId, request.receivingWarehouseId(), request.channelCode());
apply(order, request, snapshots); order.setStatus(OrderStatus.DRAFT); order.setUpdatedBy(userId);
@@ -181,20 +182,22 @@ public class OrderApplicationService {
private void validatePrototypeFields(OrderRequests.SaveRequest request) {
if ("PICKUP".equals(request.pickupMethod()) && request.sender() == null) {
throw new BizException("上门提货时必须填写发货信息");
throw new BizException(ResultCode.VALIDATION_FAILED, "上门提货时必须填写发货信息");
}
if ("PRIVATE".equals(request.destinationType()) && request.receiver() == null) {
throw new BizException("私人地址必须填写收货信息");
throw new BizException(ResultCode.VALIDATION_FAILED, "私人地址必须填写收货信息");
}
if ("FBA".equals(request.destinationType())) {
if (!StringUtils.hasText(request.amazonWarehouseCode()) || !StringUtils.hasText(request.shipmentId())
|| !StringUtils.hasText(request.referenceId())) {
throw new BizException("FBA orders require Amazon warehouse code, Shipment ID and Reference ID");
throw new BizException(ResultCode.VALIDATION_FAILED,
"FBA orders require Amazon warehouse code, Shipment ID and Reference ID");
}
for (var cargo : request.cargoes()) {
if (!StringUtils.hasText(cargo.skuNo()) || !StringUtils.hasText(cargo.upcNo())
|| !StringUtils.hasText(cargo.shipmentId()) || !StringUtils.hasText(cargo.referenceId())) {
throw new BizException("FBA cargo requires SKU NO., UPC NO., Shipment ID and Reference ID.");
throw new BizException(ResultCode.VALIDATION_FAILED,
"FBA cargo requires SKU NO., UPC NO., Shipment ID and Reference ID.");
}
}
}
@@ -216,21 +219,23 @@ public class OrderApplicationService {
if (cargoes == null || cargoes.isEmpty()) throw new BizException("At least one cargo line is required");
var parties = repository.findParties(tenantId, order.getId());
if ("PICKUP".equals(order.getPickupMethod()) && !hasParty(parties, "SENDER")) {
throw new BizException("上门提货时必须填写发货信息");
throw new BizException(ResultCode.VALIDATION_FAILED, "上门提货时必须填写发货信息");
}
if ("PRIVATE".equals(order.getDestinationType()) && !hasParty(parties, "RECEIVER")) {
throw new BizException("私人地址必须填写收货信息");
throw new BizException(ResultCode.VALIDATION_FAILED, "私人地址必须填写收货信息");
}
if ("FBA".equals(order.getDestinationType())) {
if (!StringUtils.hasText(order.getAmazonWarehouseCode()) || !StringUtils.hasText(order.getShipmentId())
|| !StringUtils.hasText(order.getReferenceId())) {
throw new BizException("FBA orders require Amazon warehouse code, Shipment ID and Reference ID");
throw new BizException(ResultCode.VALIDATION_FAILED,
"FBA orders require Amazon warehouse code, Shipment ID and Reference ID");
}
for (var cargo : cargoes) {
if (!StringUtils.hasText(cargo.getSkuNo()) || !StringUtils.hasText(cargo.getUpcNo())
|| !StringUtils.hasText(cargo.getShipmentId())
|| !StringUtils.hasText(cargo.getReferenceId())) {
throw new BizException("FBA cargo requires SKU NO., UPC NO., Shipment ID and Reference ID.");
throw new BizException(ResultCode.VALIDATION_FAILED,
"FBA cargo requires SKU NO., UPC NO., Shipment ID and Reference ID.");
}
}
}
@@ -310,7 +310,9 @@ class OrderApplicationServiceStateTest {
assertThatThrownBy(() -> service(repository, mock(OrderEligibilityGuard.class), masterData)
.updateDraft(10001L, 2L, 1L, request()))
.isInstanceOf(BizException.class)
.hasMessageContaining("不允许编辑");
.hasMessage("当前订单状态不允许编辑订单资料")
.extracting(exception -> ((BizException) exception).getResultCode())
.isEqualTo(ResultCode.CONFLICT);
verify(repository, never()).saveOrder(anyLong(), any());
}
@@ -379,7 +381,9 @@ class OrderApplicationServiceStateTest {
assertThatThrownBy(() -> service(repository, mock(OrderEligibilityGuard.class), masterData)
.createDraft(20002L, 2L, request, "pickup-without-sender"))
.isInstanceOf(BizException.class)
.hasMessageContaining("上门提货时必须填写发货信息");
.hasMessage("上门提货时必须填写发货信息")
.extracting(exception -> ((BizException) exception).getResultCode())
.isEqualTo(ResultCode.VALIDATION_FAILED);
verifyNoInteractions(masterData);
}
@@ -393,7 +397,41 @@ class OrderApplicationServiceStateTest {
assertThatThrownBy(() -> service(repository, mock(OrderEligibilityGuard.class), masterData)
.createDraft(20002L, 2L, request, "private-without-receiver"))
.isInstanceOf(BizException.class)
.hasMessageContaining("私人地址必须填写收货信息");
.hasMessage("私人地址必须填写收货信息")
.extracting(exception -> ((BizException) exception).getResultCode())
.isEqualTo(ResultCode.VALIDATION_FAILED);
verifyNoInteractions(masterData);
}
@Test
void fbaOrderStillRequiresAmazonWarehouseShipmentAndReferenceIds() {
OrderRepository repository = mock(OrderRepository.class);
OrderMasterDataGuard masterData = mock(OrderMasterDataGuard.class);
OrderRequests.SaveRequest request = fbaRequest(null, null, null);
assertThatThrownBy(() -> service(repository, mock(OrderEligibilityGuard.class), masterData)
.createDraft(20002L, 2L, request, "fba-without-order-identifiers"))
.isInstanceOf(BizException.class)
.hasMessage("FBA orders require Amazon warehouse code, Shipment ID and Reference ID")
.extracting(exception -> ((BizException) exception).getResultCode())
.isEqualTo(ResultCode.VALIDATION_FAILED);
verifyNoInteractions(masterData);
}
@Test
void fbaCargoStillRequiresSkuUpcShipmentAndReferenceIds() {
OrderRepository repository = mock(OrderRepository.class);
OrderMasterDataGuard masterData = mock(OrderMasterDataGuard.class);
OrderRequests.SaveRequest request = fbaRequest("ONT8", "FBA-SHIPMENT-1", "REF-1");
assertThatThrownBy(() -> service(repository, mock(OrderEligibilityGuard.class), masterData)
.createDraft(20002L, 2L, request, "fba-without-cargo-identifiers"))
.isInstanceOf(BizException.class)
.hasMessage("FBA cargo requires SKU NO., UPC NO., Shipment ID and Reference ID.")
.extracting(exception -> ((BizException) exception).getResultCode())
.isEqualTo(ResultCode.VALIDATION_FAILED);
verifyNoInteractions(masterData);
}
@@ -410,7 +448,9 @@ class OrderApplicationServiceStateTest {
assertThatThrownBy(() -> service(repository, mock(OrderEligibilityGuard.class), mock(OrderMasterDataGuard.class))
.transit(20002L, 2L, "u", 1L, OrderStatus.SUBMITTED, null))
.isInstanceOf(BizException.class)
.hasMessageContaining("上门提货时必须填写发货信息");
.hasMessage("上门提货时必须填写发货信息")
.extracting(exception -> ((BizException) exception).getResultCode())
.isEqualTo(ResultCode.VALIDATION_FAILED);
verify(repository, never()).saveOrder(anyLong(), any());
}
@@ -469,6 +509,19 @@ class OrderApplicationServiceStateTest {
"BUY_DECLARATION", "TAX_INCLUDED", "LCL", false, destinationType, null, null, null);
}
private OrderRequests.SaveRequest fbaRequest(String amazonWarehouseCode, String shipmentId,
String referenceId) {
OrderRequests.SaveRequest source = request(null, "SELF_EXPRESS", null, null, "FBA");
return new OrderRequests.SaveRequest(
source.customerId(), source.customerName(), source.transportMode(), source.tradeTerm(),
source.destinationCountryCode(), source.destinationWarehouseId(), source.destinationWarehouseName(),
source.expectedShipDate(), source.customerRemark(), source.sender(), source.receiver(), source.cargoes(),
source.pickupMethod(), source.receivingWarehouseId(), source.receivingWarehouseName(),
source.channelCode(), source.channelName(), source.carrierId(), source.carrierName(), source.taxMode(),
source.pricingTaxMode(), source.containerMode(), source.customsInspection(), source.destinationType(),
amazonWarehouseCode, shipmentId, referenceId);
}
private OrderMasterDataGuard.Snapshots snapshots() {
return snapshots(new PartnerClient.Partner(7L, 0L, "客户", "ACTIVE", "SHIPPER", List.of("SHIPPER")));
}