feat(wcs): persist transport orders and workflows
This commit is contained in:
@@ -0,0 +1,116 @@
|
||||
package com.ruoyi.wcs.infrastructure.persistence.task;
|
||||
|
||||
import com.ruoyi.wcs.domain.task.TaskStepType;
|
||||
import com.ruoyi.wcs.domain.task.TransportOrder;
|
||||
import com.ruoyi.wcs.domain.task.TransportOrderType;
|
||||
import com.ruoyi.wcs.domain.task.WorkflowDefinition;
|
||||
import com.ruoyi.wcs.domain.task.WorkflowInstance;
|
||||
import com.ruoyi.wcs.domain.task.WorkflowStepDefinition;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.dao.OptimisticLockingFailureException;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
|
||||
class MyBatisTransportOrderRepositoryTest {
|
||||
|
||||
@Test
|
||||
void rejectsAStateUpdateWhenThePersistedVersionChanged() {
|
||||
RecordingMapper mapper = new RecordingMapper();
|
||||
TransportOrder order = order();
|
||||
order.plan("WF-1");
|
||||
mapper.selected = TransportOrderRow.fromDomain(order);
|
||||
order.start();
|
||||
mapper.updateCount = 0;
|
||||
|
||||
MyBatisTransportOrderRepository repository =
|
||||
new MyBatisTransportOrderRepository(mapper);
|
||||
|
||||
assertThrows(OptimisticLockingFailureException.class,
|
||||
() -> repository.save(order));
|
||||
assertEquals(1L, mapper.expectedVersion);
|
||||
}
|
||||
|
||||
@Test
|
||||
void insertsANewOrderWorkflowAndItsInitialSteps() {
|
||||
RecordingMapper mapper = new RecordingMapper();
|
||||
TransportOrder order = order();
|
||||
WorkflowDefinition definition = new WorkflowDefinition(
|
||||
TransportOrderType.INBOUND,
|
||||
Arrays.asList(
|
||||
new WorkflowStepDefinition("MOVE", TaskStepType.MOVE,
|
||||
true, true, Collections.<String>emptyList()),
|
||||
new WorkflowStepDefinition("DROP", TaskStepType.UNLOAD,
|
||||
true, true, Collections.singletonList("MOVE"))));
|
||||
WorkflowInstance workflow = WorkflowInstance.create("WF-1", "ORDER-1", definition);
|
||||
order.plan(workflow.getWorkflowId());
|
||||
|
||||
new MyBatisTransportOrderRepository(mapper).save(order, workflow);
|
||||
|
||||
assertEquals(1, mapper.orderInserts);
|
||||
assertEquals(1, mapper.workflowInserts);
|
||||
assertEquals(2, mapper.stepInserts);
|
||||
assertEquals(1, mapper.dependencyInserts);
|
||||
}
|
||||
|
||||
private TransportOrder order() {
|
||||
return TransportOrder.accept(
|
||||
"ORDER-1", "REQ-1", TransportOrderType.INBOUND,
|
||||
"LOAD-1", "PORT-1", "SPACE-1", 50,
|
||||
Instant.parse("2026-08-04T00:00:00Z"));
|
||||
}
|
||||
|
||||
private static final class RecordingMapper implements TransportOrderMapper {
|
||||
private TransportOrderRow selected;
|
||||
private int updateCount = 1;
|
||||
private long expectedVersion = -1L;
|
||||
private int orderInserts;
|
||||
private int workflowInserts;
|
||||
private int stepInserts;
|
||||
private int dependencyInserts;
|
||||
|
||||
@Override
|
||||
public TransportOrderRow selectByExternalRequestId(String externalRequestId) {
|
||||
return selected;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TransportOrderRow selectByOrderId(String orderId) {
|
||||
return selected;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int insertOrder(TransportOrderRow row) {
|
||||
orderInserts++;
|
||||
return 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int updateState(TransportOrderRow row, long expectedVersion) {
|
||||
this.expectedVersion = expectedVersion;
|
||||
return updateCount;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int insertWorkflow(WorkflowRow row) {
|
||||
workflowInserts++;
|
||||
return 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int insertTaskStep(TaskStepRow row) {
|
||||
stepInserts++;
|
||||
return 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int insertTaskDependency(TaskDependencyRow row) {
|
||||
dependencyInserts++;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
package com.ruoyi.wcs.infrastructure.persistence.task;
|
||||
|
||||
import org.apache.ibatis.builder.xml.XMLMapperBuilder;
|
||||
import org.apache.ibatis.session.Configuration;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.io.InputStream;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
class TransportOrderMapperXmlTest {
|
||||
|
||||
@Test
|
||||
void registersAllFoundationPersistenceStatements() {
|
||||
String resource = "mapper/wcs/task/TransportOrderMapper.xml";
|
||||
InputStream input = getClass().getClassLoader().getResourceAsStream(resource);
|
||||
assertNotNull(input, "missing " + resource);
|
||||
|
||||
Configuration configuration = new Configuration();
|
||||
XMLMapperBuilder builder = new XMLMapperBuilder(
|
||||
input, configuration, resource, configuration.getSqlFragments());
|
||||
builder.parse();
|
||||
|
||||
String namespace = TransportOrderMapper.class.getName() + ".";
|
||||
assertTrue(configuration.hasStatement(namespace + "selectByExternalRequestId"));
|
||||
assertTrue(configuration.hasStatement(namespace + "insertOrder"));
|
||||
assertTrue(configuration.hasStatement(namespace + "updateState"));
|
||||
assertTrue(configuration.hasStatement(namespace + "insertWorkflow"));
|
||||
assertTrue(configuration.hasStatement(namespace + "insertTaskStep"));
|
||||
assertTrue(configuration.hasStatement(namespace + "insertTaskDependency"));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
package com.ruoyi.wcs.infrastructure.persistence.task;
|
||||
|
||||
import com.ruoyi.wcs.domain.task.TransportOrder;
|
||||
import com.ruoyi.wcs.domain.task.TransportOrderType;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.time.Instant;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
class TransportOrderRowMapperTest {
|
||||
|
||||
@Test
|
||||
void preservesOrderStateAndVersionAcrossPersistenceMapping() {
|
||||
TransportOrder source = TransportOrder.accept(
|
||||
"ORDER-1", "REQ-1", TransportOrderType.OUTBOUND,
|
||||
"LOAD-1", "SPACE-1", "PORT-1", 80,
|
||||
Instant.parse("2026-08-04T00:00:00Z"));
|
||||
source.plan("WF-1");
|
||||
source.start();
|
||||
source.clearUncommittedEvents();
|
||||
|
||||
TransportOrderRow row = TransportOrderRow.fromDomain(source);
|
||||
TransportOrder restored = row.toDomain();
|
||||
|
||||
assertEquals(source.getState(), restored.getState());
|
||||
assertEquals(2L, restored.getStateVersion());
|
||||
assertEquals("WF-1", restored.getWorkflowId());
|
||||
assertTrue(restored.getUncommittedEvents().isEmpty());
|
||||
}
|
||||
|
||||
@Test
|
||||
void mapsNullableLoadAndResultFieldsWithoutInventingValues() {
|
||||
TransportOrder source = TransportOrder.accept(
|
||||
"ORDER-2", "REQ-2", TransportOrderType.INVENTORY,
|
||||
null, "SPACE-2", "SPACE-2", 10,
|
||||
Instant.parse("2026-08-04T00:00:00Z"));
|
||||
|
||||
TransportOrder restored = TransportOrderRow.fromDomain(source).toDomain();
|
||||
|
||||
assertEquals(null, restored.getLoadId());
|
||||
assertEquals(null, restored.getResultCode());
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user