Files
baiyue-firstleg/firstleg/src/test/java/com/baiyue/firstleg/service/MeasurementBatchServiceTest.java
T
2026-08-18 15:43:58 +08:00

168 lines
8.0 KiB
Java

package com.baiyue.firstleg.service;
import com.baiyue.common.core.exception.BizException;
import com.baiyue.firstleg.dto.MeasurementBatchCommand;
import com.baiyue.firstleg.domain.CustomerDimensionBoxType;
import com.baiyue.firstleg.entity.CustomerDimensionConfigEntity;
import com.baiyue.firstleg.entity.InboundMeasurementEntity;
import com.baiyue.firstleg.entity.InboundMeasurementItemEntity;
import com.baiyue.firstleg.entity.InboundOrderEntity;
import com.baiyue.firstleg.repository.InboundMeasurementRepository;
import com.baiyue.firstleg.repository.CustomerDimensionConfigRepository;
import jakarta.annotation.Resource;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.mockito.ArgumentCaptor;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.List;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@DisplayName("测量批次共享领域服务")
@SpringJUnitConfig({MeasurementBatchService.class, CustomerDimensionWeightingService.class})
class MeasurementBatchServiceTest {
@MockBean private InboundMeasurementRepository repository;
@MockBean private CustomerDimensionConfigRepository dimensionConfigs;
@Resource private MeasurementBatchService service;
@BeforeEach
void setUp() {
when(repository.findInbound(1L, 10L)).thenReturn(inbound());
when(dimensionConfigs.findAll(1L)).thenReturn(dimensionRules(1L));
org.mockito.Mockito.doAnswer(invocation -> {
InboundMeasurementEntity entity = invocation.getArgument(0);
entity.setId(100L);
return null;
}).when(repository).insertMeasurement(any());
}
@Test
void manualAndExternalUseSameTablesAndExternalSaveNeverAdvancesInbound() {
MeasurementBatchCommand command = new MeasurementBatchCommand(
1L, 10L, null, 0, "THIRD_PARTY", "DEVICE_VENDOR", "EVENT-001",
"D-01", "YW-01", LocalDateTime.now(), "{}", null, null, null,
null, 0L, List.of(item(null)));
InboundMeasurementEntity saved = service.saveBatch(command);
assertThat(saved.getSourceType()).isEqualTo("THIRD_PARTY");
assertThat(saved.getStatus()).isEqualTo("RECEIVED");
assertThat(saved.getTotalPackageCount()).isEqualTo(2);
ArgumentCaptor<List<InboundMeasurementItemEntity>> items = ArgumentCaptor.forClass(List.class);
verify(repository).replaceItems(org.mockito.ArgumentMatchers.eq(1L),
org.mockito.ArgumentMatchers.eq(100L), items.capture());
assertThat(items.getValue().get(0).getUnitVolumeCbm()).isEqualByComparingTo("0.0510");
assertThat(items.getValue().get(0).getTotalVolumeCbm()).isEqualByComparingTo("0.1020");
assertThat(items.getValue().get(0).getOuterLengthCm()).isEqualByComparingTo("44.000");
assertThat(items.getValue().get(0).getOuterWidthCm()).isEqualByComparingTo("34.000");
assertThat(items.getValue().get(0).getOuterHeightCm()).isEqualByComparingTo("34.000");
assertThat(items.getValue().get(0).getCalculationRuleVersion())
.isEqualTo("CUSTOMER_DIMENSION_MEDIUM_V0");
assertThat(items.getValue().get(0).getGirthCm()).isEqualByComparingTo("140.000");
verify(repository, never()).updateInbound(any());
}
@Test
void manualDraftCalculatesVolumeAndVolumeWeightOnServer() {
MeasurementBatchCommand command = new MeasurementBatchCommand(
1L, 10L, null, 0, "MANUAL", "PLATFORM", null, null, null,
LocalDateTime.now(), null, "CKW-1", new BigDecimal("20"),
new BigDecimal("0.1"), "服装", 9L, List.of(item(new BigDecimal("3.25"))));
InboundMeasurementEntity saved = service.saveBatch(command);
assertThat(saved.getStatus()).isEqualTo("DRAFT");
assertThat(saved.getTotalVolumeCbm()).isEqualByComparingTo("0.1020");
assertThat(saved.getVolumeWeightKg()).isEqualByComparingTo("17.034");
ArgumentCaptor<List<InboundMeasurementItemEntity>> items = ArgumentCaptor.forClass(List.class);
verify(repository).replaceItems(org.mockito.ArgumentMatchers.eq(1L),
org.mockito.ArgumentMatchers.eq(100L), items.capture());
assertThat(items.getValue().get(0).getInboundDetailId()).isEqualTo(80001L);
}
@Test
void staleDraftVersionIsRejectedBeforeReplacingItems() {
InboundMeasurementEntity existing = new InboundMeasurementEntity();
existing.setId(100L);
existing.setTenantId(1L);
existing.setInboundId(10L);
existing.setSourceType("MANUAL");
existing.setStatus("DRAFT");
existing.setVersion(3);
when(repository.findMeasurement(1L, 10L, 100L)).thenReturn(existing);
MeasurementBatchCommand command = new MeasurementBatchCommand(
1L, 10L, 100L, 2, "MANUAL", "PLATFORM", null, null, null,
LocalDateTime.now(), null, null, null, null, null, 9L,
List.of(item(BigDecimal.ONE)));
assertThatThrownBy(() -> service.saveBatch(command))
.isInstanceOf(BizException.class)
.hasMessageContaining("其他人修改");
verify(repository, never()).replaceItems(
org.mockito.ArgumentMatchers.anyLong(), org.mockito.ArgumentMatchers.anyLong(), any());
}
@Test
void approvedManualMeasurementCanBeEditedAsDraftBeforeReviewCompletes() {
InboundMeasurementEntity existing = new InboundMeasurementEntity();
existing.setId(100L);
existing.setTenantId(1L);
existing.setInboundId(10L);
existing.setSourceType("MANUAL");
existing.setStatus("APPROVED");
existing.setVersion(3);
when(repository.findMeasurement(1L, 10L, 100L)).thenReturn(existing);
when(repository.updateMeasurement(existing)).thenReturn(true);
MeasurementBatchCommand command = new MeasurementBatchCommand(
1L, 10L, 100L, 3, "MANUAL", "PLATFORM", null, null, null,
LocalDateTime.now(), null, "CKW-2", new BigDecimal("21"),
new BigDecimal("0.2"), "服装", 9L, List.of(item(BigDecimal.ONE)));
InboundMeasurementEntity saved = service.saveBatch(command);
assertThat(saved.getStatus()).isEqualTo("DRAFT");
verify(repository).updateMeasurement(existing);
verify(repository).replaceItems(org.mockito.ArgumentMatchers.eq(1L),
org.mockito.ArgumentMatchers.eq(100L), any());
}
private MeasurementBatchCommand.Item item(BigDecimal unitWeight) {
return new MeasurementBatchCommand.Item(
80001L, "001", "A", 2, new BigDecimal("40"), new BigDecimal("30"),
new BigDecimal("20"), 500L, null,
new BigDecimal("41"), new BigDecimal("31"), new BigDecimal("21"), "备注");
}
private InboundOrderEntity inbound() {
InboundOrderEntity inbound = new InboundOrderEntity();
inbound.setId(10L);
inbound.setTenantId(1L);
inbound.setProcessStatus("WAIT_MEASURE");
inbound.setVersion(0);
return inbound;
}
private List<CustomerDimensionConfigEntity> dimensionRules(long tenantId) {
return java.util.Arrays.stream(CustomerDimensionBoxType.values()).map(type -> {
CustomerDimensionConfigEntity rule = new CustomerDimensionConfigEntity();
rule.setTenantId(tenantId); rule.setBoxType(type); rule.setVersion(0);
rule.setInnerLengthCm(type.defaultLengthCm()); rule.setInnerWidthCm(type.defaultWidthCm());
rule.setInnerHeightCm(type.defaultHeightCm());
rule.setEdgeAdditionCm(new BigDecimal("2.000"));
return rule;
}).toList();
}
}