Merge branch 'test' of http://8.163.30.128:10082/java-project/baiyue-firstleg into test
This commit is contained in:
@@ -34,6 +34,17 @@ public class FulfillmentTaskRepository {
|
|||||||
.eq(FulfillmentTaskEntity::getOrderId, orderId));
|
.eq(FulfillmentTaskEntity::getOrderId, orderId));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public FulfillmentTaskEntity findByOrderForUpdate(long tenantId, long orderId) {
|
||||||
|
return tasks.selectOne(new LambdaQueryWrapper<FulfillmentTaskEntity>()
|
||||||
|
.eq(FulfillmentTaskEntity::getTenantId, tenantId)
|
||||||
|
.eq(FulfillmentTaskEntity::getOrderId, orderId)
|
||||||
|
.last("FOR UPDATE"));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void insert(FulfillmentTaskEntity task) {
|
||||||
|
tasks.insert(task);
|
||||||
|
}
|
||||||
|
|
||||||
public PageResult<FulfillmentTaskEntity> page(long tenantId, FulfillmentTaskQuery query) {
|
public PageResult<FulfillmentTaskEntity> page(long tenantId, FulfillmentTaskQuery query) {
|
||||||
LambdaQueryWrapper<FulfillmentTaskEntity> wrapper = new LambdaQueryWrapper<FulfillmentTaskEntity>()
|
LambdaQueryWrapper<FulfillmentTaskEntity> wrapper = new LambdaQueryWrapper<FulfillmentTaskEntity>()
|
||||||
.eq(FulfillmentTaskEntity::getTenantId, tenantId)
|
.eq(FulfillmentTaskEntity::getTenantId, tenantId)
|
||||||
|
|||||||
+74
@@ -0,0 +1,74 @@
|
|||||||
|
package com.baiyue.firstleg.service;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
|
||||||
|
import com.baiyue.common.core.api.ResultCode;
|
||||||
|
import com.baiyue.common.core.exception.BizException;
|
||||||
|
import com.baiyue.firstleg.dto.OrderApprovedInboundCommand;
|
||||||
|
import com.baiyue.firstleg.entity.FulfillmentTaskEntity;
|
||||||
|
import com.baiyue.firstleg.repository.FulfillmentTaskRepository;
|
||||||
|
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
import org.springframework.dao.DuplicateKeyException;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
/** 将订单审核快照幂等转换为待分配履约任务。 */
|
||||||
|
@Service
|
||||||
|
public class FulfillmentTaskProvisioningService {
|
||||||
|
private final FulfillmentTaskRepository repository;
|
||||||
|
private final ObjectMapper objectMapper;
|
||||||
|
|
||||||
|
public FulfillmentTaskProvisioningService(FulfillmentTaskRepository repository, ObjectMapper objectMapper) {
|
||||||
|
this.repository = repository;
|
||||||
|
this.objectMapper = objectMapper;
|
||||||
|
}
|
||||||
|
|
||||||
|
public FulfillmentTaskEntity provision(OrderApprovedInboundCommand command, LocalDateTime now) {
|
||||||
|
FulfillmentTaskEntity existing = repository.findByOrder(command.tenantId(), command.orderId());
|
||||||
|
if (existing != null) {
|
||||||
|
return requireMatchingOrder(existing, command.orderNo());
|
||||||
|
}
|
||||||
|
|
||||||
|
FulfillmentTaskEntity task = new FulfillmentTaskEntity();
|
||||||
|
task.setId(IdWorker.getId());
|
||||||
|
task.setTenantId(command.tenantId());
|
||||||
|
task.setOrderId(command.orderId());
|
||||||
|
task.setOrderNo(command.orderNo());
|
||||||
|
task.setOrderSnapshotJson(snapshot(command));
|
||||||
|
task.setStatus("PENDING_ASSIGNMENT");
|
||||||
|
task.setCreatedBy(0L);
|
||||||
|
task.setUpdatedBy(0L);
|
||||||
|
task.setCreatedAt(now);
|
||||||
|
task.setUpdatedAt(now);
|
||||||
|
task.setDeleted(false);
|
||||||
|
task.setVersion(0);
|
||||||
|
try {
|
||||||
|
repository.insert(task);
|
||||||
|
return task;
|
||||||
|
} catch (DuplicateKeyException duplicate) {
|
||||||
|
FulfillmentTaskEntity winner = repository.findByOrderForUpdate(
|
||||||
|
command.tenantId(), command.orderId());
|
||||||
|
if (winner == null) {
|
||||||
|
throw new BizException(ResultCode.CONFLICT, "履约任务已被并发创建但无法读取");
|
||||||
|
}
|
||||||
|
return requireMatchingOrder(winner, command.orderNo());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private String snapshot(OrderApprovedInboundCommand command) {
|
||||||
|
try {
|
||||||
|
return objectMapper.writeValueAsString(command);
|
||||||
|
} catch (JsonProcessingException exception) {
|
||||||
|
throw new BizException(ResultCode.INTERNAL_ERROR, "订单履约快照序列化失败");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private FulfillmentTaskEntity requireMatchingOrder(FulfillmentTaskEntity task, String orderNo) {
|
||||||
|
if (!Objects.equals(task.getOrderNo(), orderNo)) {
|
||||||
|
throw new BizException(ResultCode.CONFLICT, "订单号与已有履约任务不一致");
|
||||||
|
}
|
||||||
|
return task;
|
||||||
|
}
|
||||||
|
}
|
||||||
+32
-1
@@ -7,6 +7,7 @@ import com.baiyue.common.core.api.ResultCode;
|
|||||||
import com.baiyue.common.core.exception.BizException;
|
import com.baiyue.common.core.exception.BizException;
|
||||||
import com.baiyue.firstleg.dto.OrderApprovedInboundCommand;
|
import com.baiyue.firstleg.dto.OrderApprovedInboundCommand;
|
||||||
import com.baiyue.firstleg.dto.InboundOrderReference;
|
import com.baiyue.firstleg.dto.InboundOrderReference;
|
||||||
|
import com.baiyue.firstleg.entity.FulfillmentTaskEntity;
|
||||||
import com.baiyue.firstleg.entity.InboundOrderEntity;
|
import com.baiyue.firstleg.entity.InboundOrderEntity;
|
||||||
import com.baiyue.firstleg.entity.InboundStatusHistoryEntity;
|
import com.baiyue.firstleg.entity.InboundStatusHistoryEntity;
|
||||||
import com.baiyue.firstleg.mapper.InboundOrderMapper;
|
import com.baiyue.firstleg.mapper.InboundOrderMapper;
|
||||||
@@ -25,18 +26,25 @@ public class InboundOrderCreationService {
|
|||||||
private InboundOrderMapper orders;
|
private InboundOrderMapper orders;
|
||||||
@Resource
|
@Resource
|
||||||
private InboundStatusHistoryMapper histories;
|
private InboundStatusHistoryMapper histories;
|
||||||
|
@Resource
|
||||||
|
private FulfillmentTaskProvisioningService fulfillmentTasks;
|
||||||
|
|
||||||
@Transactional
|
@Transactional
|
||||||
public long createFromApprovedOrder(OrderApprovedInboundCommand command) {
|
public long createFromApprovedOrder(OrderApprovedInboundCommand command) {
|
||||||
InboundOrderEntity existing = findByOrder(command.tenantId(), command.orderId(), false);
|
InboundOrderEntity existing = findByOrder(command.tenantId(), command.orderId(), false);
|
||||||
if (existing != null) {
|
if (existing != null) {
|
||||||
return requireMatchingInboundCode(existing, command.inboundCode());
|
long inboundId = requireMatchingInboundCode(existing, command.inboundCode());
|
||||||
|
FulfillmentTaskEntity task = fulfillmentTasks.provision(command, LocalDateTime.now());
|
||||||
|
linkTask(existing, task.getId());
|
||||||
|
return inboundId;
|
||||||
}
|
}
|
||||||
|
|
||||||
LocalDateTime now = LocalDateTime.now();
|
LocalDateTime now = LocalDateTime.now();
|
||||||
|
FulfillmentTaskEntity task = fulfillmentTasks.provision(command, now);
|
||||||
InboundOrderEntity inbound = new InboundOrderEntity();
|
InboundOrderEntity inbound = new InboundOrderEntity();
|
||||||
inbound.setId(IdWorker.getId());
|
inbound.setId(IdWorker.getId());
|
||||||
inbound.setTenantId(command.tenantId());
|
inbound.setTenantId(command.tenantId());
|
||||||
|
inbound.setTaskId(task.getId());
|
||||||
inbound.setOrderId(command.orderId());
|
inbound.setOrderId(command.orderId());
|
||||||
inbound.setOrderNo(command.orderNo());
|
inbound.setOrderNo(command.orderNo());
|
||||||
inbound.setInboundCode(command.inboundCode());
|
inbound.setInboundCode(command.inboundCode());
|
||||||
@@ -116,6 +124,29 @@ public class InboundOrderCreationService {
|
|||||||
return existing.getId();
|
return existing.getId();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void linkTask(InboundOrderEntity inbound, long taskId) {
|
||||||
|
if (inbound.getTaskId() != null) {
|
||||||
|
if (!inbound.getTaskId().equals(taskId)) {
|
||||||
|
throw new BizException(ResultCode.CONFLICT, "入库单已关联其他履约任务");
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
int updated = orders.update(null,
|
||||||
|
new com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper<InboundOrderEntity>()
|
||||||
|
.eq(InboundOrderEntity::getTenantId, inbound.getTenantId())
|
||||||
|
.eq(InboundOrderEntity::getId, inbound.getId())
|
||||||
|
.isNull(InboundOrderEntity::getTaskId)
|
||||||
|
.set(InboundOrderEntity::getTaskId, taskId));
|
||||||
|
if (updated == 1) {
|
||||||
|
inbound.setTaskId(taskId);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
InboundOrderEntity current = findByOrder(inbound.getTenantId(), inbound.getOrderId(), true);
|
||||||
|
if (current == null || !Long.valueOf(taskId).equals(current.getTaskId())) {
|
||||||
|
throw new BizException(ResultCode.CONFLICT, "入库单履约任务关联已发生变化");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public List<InboundOrderReference.Item> findReferences(long tenantId, List<Long> orderIds) {
|
public List<InboundOrderReference.Item> findReferences(long tenantId, List<Long> orderIds) {
|
||||||
if (orderIds.isEmpty()) return List.of();
|
if (orderIds.isEmpty()) return List.of();
|
||||||
return orders.selectList(new com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper<InboundOrderEntity>()
|
return orders.selectList(new com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper<InboundOrderEntity>()
|
||||||
|
|||||||
+84
@@ -0,0 +1,84 @@
|
|||||||
|
package com.baiyue.firstleg.service;
|
||||||
|
|
||||||
|
import com.baiyue.firstleg.dto.OrderApprovedInboundCommand;
|
||||||
|
import com.baiyue.firstleg.entity.FulfillmentTaskEntity;
|
||||||
|
import com.baiyue.firstleg.repository.FulfillmentTaskRepository;
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
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.Mock;
|
||||||
|
import org.mockito.junit.jupiter.MockitoExtension;
|
||||||
|
import org.springframework.dao.DuplicateKeyException;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
import static org.mockito.ArgumentMatchers.any;
|
||||||
|
import static org.mockito.Mockito.doThrow;
|
||||||
|
import static org.mockito.Mockito.never;
|
||||||
|
import static org.mockito.Mockito.verify;
|
||||||
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
|
@ExtendWith(MockitoExtension.class)
|
||||||
|
class FulfillmentTaskProvisioningServiceTest {
|
||||||
|
private static final LocalDateTime NOW = LocalDateTime.of(2026, 8, 8, 10, 0);
|
||||||
|
@Mock private FulfillmentTaskRepository repository;
|
||||||
|
private FulfillmentTaskProvisioningService service;
|
||||||
|
|
||||||
|
@BeforeEach
|
||||||
|
void setUp() {
|
||||||
|
service = new FulfillmentTaskProvisioningService(repository, new ObjectMapper().findAndRegisterModules());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void shouldCreatePendingTaskFromApprovedOrderSnapshot() {
|
||||||
|
FulfillmentTaskEntity created = service.provision(command(), NOW);
|
||||||
|
|
||||||
|
ArgumentCaptor<FulfillmentTaskEntity> captor = ArgumentCaptor.forClass(FulfillmentTaskEntity.class);
|
||||||
|
verify(repository).insert(captor.capture());
|
||||||
|
assertThat(created).isSameAs(captor.getValue());
|
||||||
|
assertThat(created.getTenantId()).isEqualTo(10001L);
|
||||||
|
assertThat(created.getOrderId()).isEqualTo(77L);
|
||||||
|
assertThat(created.getOrderNo()).isEqualTo("FL-77");
|
||||||
|
assertThat(created.getStatus()).isEqualTo("PENDING_ASSIGNMENT");
|
||||||
|
assertThat(created.getOrderSnapshotJson()).contains("\"tenantId\":10001", "\"orderId\":77", "\"inboundCode\":\"RK-77\"");
|
||||||
|
assertThat(created.getCreatedAt()).isEqualTo(NOW);
|
||||||
|
assertThat(created.getDeleted()).isFalse();
|
||||||
|
assertThat(created.getVersion()).isZero();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void shouldReturnExistingTaskForIdempotentReplay() {
|
||||||
|
FulfillmentTaskEntity existing = task(700L);
|
||||||
|
when(repository.findByOrder(10001L, 77L)).thenReturn(existing);
|
||||||
|
|
||||||
|
assertThat(service.provision(command(), NOW)).isSameAs(existing);
|
||||||
|
|
||||||
|
verify(repository, never()).insert(any());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void shouldConvergeOnConcurrentTaskCreation() {
|
||||||
|
FulfillmentTaskEntity winner = task(701L);
|
||||||
|
doThrow(new DuplicateKeyException("concurrent insert")).when(repository).insert(any());
|
||||||
|
when(repository.findByOrderForUpdate(10001L, 77L)).thenReturn(winner);
|
||||||
|
|
||||||
|
assertThat(service.provision(command(), NOW)).isSameAs(winner);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static FulfillmentTaskEntity task(long id) {
|
||||||
|
FulfillmentTaskEntity task = new FulfillmentTaskEntity();
|
||||||
|
task.setId(id); task.setTenantId(10001L); task.setOrderId(77L); task.setOrderNo("FL-77");
|
||||||
|
return task;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static OrderApprovedInboundCommand command() {
|
||||||
|
return new OrderApprovedInboundCommand(
|
||||||
|
10001L, 77L, "FL-77", "RK-77", 7L, "测试客户", 9L, "义乌仓",
|
||||||
|
null, null, null, "FBA", "AIR", "空运", null, null,
|
||||||
|
"BUY_DECLARATION", "TAX_EXCLUDED", null, null, "FBA", null,
|
||||||
|
"ONT8", "ONT8", "验收备注", null, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -51,6 +51,18 @@ class FulfillmentTaskServiceTest {
|
|||||||
.isEqualTo(ResultCode.NOT_FOUND);
|
.isEqualTo(ResultCode.NOT_FOUND);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("按客户和订单查询返回审核后生成的履约任务")
|
||||||
|
void shouldReturnProvisionedTaskByTenantAndOrder() {
|
||||||
|
FulfillmentTaskEntity task = new FulfillmentTaskEntity();
|
||||||
|
task.setId(700L); task.setTenantId(10001L); task.setOrderId(77L);
|
||||||
|
when(repository.findByOrder(10001L, 77L)).thenReturn(task);
|
||||||
|
|
||||||
|
assertThat(service.byOrder(10001L, 77L)).isSameAs(task);
|
||||||
|
|
||||||
|
verify(repository).findByOrder(10001L, 77L);
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@DisplayName("查询分配历史前先校验任务归属租户")
|
@DisplayName("查询分配历史前先校验任务归属租户")
|
||||||
void shouldVerifyTaskTenantBeforeLoadingAssignmentHistory() {
|
void shouldVerifyTaskTenantBeforeLoadingAssignmentHistory() {
|
||||||
|
|||||||
+41
@@ -1,15 +1,20 @@
|
|||||||
package com.baiyue.firstleg.service;
|
package com.baiyue.firstleg.service;
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.core.conditions.Wrapper;
|
import com.baomidou.mybatisplus.core.conditions.Wrapper;
|
||||||
|
import com.baomidou.mybatisplus.core.MybatisConfiguration;
|
||||||
|
import com.baomidou.mybatisplus.core.metadata.TableInfoHelper;
|
||||||
import com.baiyue.firstleg.dto.OrderApprovedInboundCommand;
|
import com.baiyue.firstleg.dto.OrderApprovedInboundCommand;
|
||||||
import com.baiyue.common.core.api.ResultCode;
|
import com.baiyue.common.core.api.ResultCode;
|
||||||
import com.baiyue.common.core.exception.BizException;
|
import com.baiyue.common.core.exception.BizException;
|
||||||
import com.baiyue.firstleg.entity.InboundOrderEntity;
|
import com.baiyue.firstleg.entity.InboundOrderEntity;
|
||||||
import com.baiyue.firstleg.entity.InboundStatusHistoryEntity;
|
import com.baiyue.firstleg.entity.InboundStatusHistoryEntity;
|
||||||
|
import com.baiyue.firstleg.entity.FulfillmentTaskEntity;
|
||||||
import com.baiyue.firstleg.mapper.InboundOrderMapper;
|
import com.baiyue.firstleg.mapper.InboundOrderMapper;
|
||||||
import com.baiyue.firstleg.mapper.InboundStatusHistoryMapper;
|
import com.baiyue.firstleg.mapper.InboundStatusHistoryMapper;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.junit.jupiter.api.BeforeAll;
|
||||||
import org.junit.jupiter.api.extension.ExtendWith;
|
import org.junit.jupiter.api.extension.ExtendWith;
|
||||||
|
import org.apache.ibatis.builder.MapperBuilderAssistant;
|
||||||
import org.mockito.ArgumentCaptor;
|
import org.mockito.ArgumentCaptor;
|
||||||
import org.mockito.InjectMocks;
|
import org.mockito.InjectMocks;
|
||||||
import org.mockito.Mock;
|
import org.mockito.Mock;
|
||||||
@@ -26,10 +31,18 @@ import static org.mockito.Mockito.when;
|
|||||||
|
|
||||||
@ExtendWith(MockitoExtension.class)
|
@ExtendWith(MockitoExtension.class)
|
||||||
class InboundOrderCreationServiceTest {
|
class InboundOrderCreationServiceTest {
|
||||||
|
@BeforeAll
|
||||||
|
static void initializeMetadata() {
|
||||||
|
TableInfoHelper.initTableInfo(
|
||||||
|
new MapperBuilderAssistant(new MybatisConfiguration(), "test"), InboundOrderEntity.class);
|
||||||
|
}
|
||||||
|
|
||||||
@Mock
|
@Mock
|
||||||
private InboundOrderMapper orders;
|
private InboundOrderMapper orders;
|
||||||
@Mock
|
@Mock
|
||||||
private InboundStatusHistoryMapper histories;
|
private InboundStatusHistoryMapper histories;
|
||||||
|
@Mock
|
||||||
|
private FulfillmentTaskProvisioningService fulfillmentTasks;
|
||||||
@InjectMocks
|
@InjectMocks
|
||||||
private InboundOrderCreationService service;
|
private InboundOrderCreationService service;
|
||||||
|
|
||||||
@@ -41,7 +54,9 @@ class InboundOrderCreationServiceTest {
|
|||||||
existing.setTenantId(10001L);
|
existing.setTenantId(10001L);
|
||||||
existing.setOrderId(77L);
|
existing.setOrderId(77L);
|
||||||
existing.setInboundCode("RK-CUSTOM-77");
|
existing.setInboundCode("RK-CUSTOM-77");
|
||||||
|
existing.setTaskId(700L);
|
||||||
when(orders.selectOne(any(Wrapper.class))).thenReturn(null, existing);
|
when(orders.selectOne(any(Wrapper.class))).thenReturn(null, existing);
|
||||||
|
when(fulfillmentTasks.provision(any(), any())).thenReturn(task(700L));
|
||||||
|
|
||||||
long createdId = service.createFromApprovedOrder(command);
|
long createdId = service.createFromApprovedOrder(command);
|
||||||
long replayedId = service.createFromApprovedOrder(command);
|
long replayedId = service.createFromApprovedOrder(command);
|
||||||
@@ -50,6 +65,7 @@ class InboundOrderCreationServiceTest {
|
|||||||
verify(orders, times(1)).insert(inboundCaptor.capture());
|
verify(orders, times(1)).insert(inboundCaptor.capture());
|
||||||
verify(histories, times(1)).insert(any(InboundStatusHistoryEntity.class));
|
verify(histories, times(1)).insert(any(InboundStatusHistoryEntity.class));
|
||||||
assertThat(inboundCaptor.getValue().getInboundCode()).isEqualTo("RK-CUSTOM-77");
|
assertThat(inboundCaptor.getValue().getInboundCode()).isEqualTo("RK-CUSTOM-77");
|
||||||
|
assertThat(inboundCaptor.getValue().getTaskId()).isEqualTo(700L);
|
||||||
assertThat(inboundCaptor.getValue().getCarrierId()).isNull();
|
assertThat(inboundCaptor.getValue().getCarrierId()).isNull();
|
||||||
assertThat(inboundCaptor.getValue().getTaxMode()).isEqualTo("BUY_DECLARATION");
|
assertThat(inboundCaptor.getValue().getTaxMode()).isEqualTo("BUY_DECLARATION");
|
||||||
assertThat(inboundCaptor.getValue().getPricingTaxMode()).isEqualTo("TAX_EXCLUDED");
|
assertThat(inboundCaptor.getValue().getPricingTaxMode()).isEqualTo("TAX_EXCLUDED");
|
||||||
@@ -73,7 +89,9 @@ class InboundOrderCreationServiceTest {
|
|||||||
@Test
|
@Test
|
||||||
void shouldConvergeOnConcurrentDuplicateInsertWinner() {
|
void shouldConvergeOnConcurrentDuplicateInsertWinner() {
|
||||||
InboundOrderEntity winner = inbound(901L, "RK-CUSTOM-77", "UNPRICED", null, null);
|
InboundOrderEntity winner = inbound(901L, "RK-CUSTOM-77", "UNPRICED", null, null);
|
||||||
|
winner.setTaskId(700L);
|
||||||
when(orders.selectOne(any(Wrapper.class))).thenReturn(null, winner);
|
when(orders.selectOne(any(Wrapper.class))).thenReturn(null, winner);
|
||||||
|
when(fulfillmentTasks.provision(any(), any())).thenReturn(task(700L));
|
||||||
doThrow(new org.springframework.dao.DuplicateKeyException("concurrent insert"))
|
doThrow(new org.springframework.dao.DuplicateKeyException("concurrent insert"))
|
||||||
.when(orders).insert(any(InboundOrderEntity.class));
|
.when(orders).insert(any(InboundOrderEntity.class));
|
||||||
|
|
||||||
@@ -81,6 +99,20 @@ class InboundOrderCreationServiceTest {
|
|||||||
verify(histories, never()).insert(any(InboundStatusHistoryEntity.class));
|
verify(histories, never()).insert(any(InboundStatusHistoryEntity.class));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void shouldBackfillTaskLinkForInboundCreatedBeforeTaskProvisioning() {
|
||||||
|
InboundOrderEntity existing = inbound(900L, "RK-CUSTOM-77", "UNPRICED", null, null);
|
||||||
|
when(orders.selectOne(any(Wrapper.class))).thenReturn(existing);
|
||||||
|
when(orders.update(any(), any(Wrapper.class))).thenReturn(1);
|
||||||
|
when(fulfillmentTasks.provision(any(), any())).thenReturn(task(700L));
|
||||||
|
|
||||||
|
assertThat(service.createFromApprovedOrder(approvedCommand("RK-CUSTOM-77"))).isEqualTo(900L);
|
||||||
|
|
||||||
|
assertThat(existing.getTaskId()).isEqualTo(700L);
|
||||||
|
verify(orders).update(any(), any(Wrapper.class));
|
||||||
|
verify(orders, never()).insert(any(InboundOrderEntity.class));
|
||||||
|
}
|
||||||
|
|
||||||
private static InboundOrderEntity inbound(long id, String code, String feeStatus,
|
private static InboundOrderEntity inbound(long id, String code, String feeStatus,
|
||||||
Long carrierId, String carrierName) {
|
Long carrierId, String carrierName) {
|
||||||
InboundOrderEntity inbound = new InboundOrderEntity();
|
InboundOrderEntity inbound = new InboundOrderEntity();
|
||||||
@@ -94,6 +126,15 @@ class InboundOrderCreationServiceTest {
|
|||||||
return inbound;
|
return inbound;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static FulfillmentTaskEntity task(long id) {
|
||||||
|
FulfillmentTaskEntity task = new FulfillmentTaskEntity();
|
||||||
|
task.setId(id);
|
||||||
|
task.setTenantId(10001L);
|
||||||
|
task.setOrderId(77L);
|
||||||
|
task.setOrderNo("FL-77");
|
||||||
|
return task;
|
||||||
|
}
|
||||||
|
|
||||||
private static OrderApprovedInboundCommand approvedCommand(String inboundCode) {
|
private static OrderApprovedInboundCommand approvedCommand(String inboundCode) {
|
||||||
return new OrderApprovedInboundCommand(
|
return new OrderApprovedInboundCommand(
|
||||||
10001L, 77L, "FL-77", inboundCode, 7L, "测试客户", 9L, "义乌仓",
|
10001L, 77L, "FL-77", inboundCode, 7L, "测试客户", 9L, "义乌仓",
|
||||||
|
|||||||
Reference in New Issue
Block a user