package cn.iocoder.yudao.module.mes.service.md.item;
|
|
import cn.iocoder.yudao.module.mes.controller.admin.md.item.vo.bom.MesMdProductBomSaveReqVO;
|
import cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdItemDO;
|
import cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdProductBomDO;
|
import cn.iocoder.yudao.module.mes.dal.mysql.md.item.MesMdProductBomMapper;
|
import cn.iocoder.yudao.module.system.api.agent.imports.AgentImportCommitReqVO;
|
import cn.iocoder.yudao.module.system.api.agent.imports.AgentImportPreflightReqVO;
|
import cn.iocoder.yudao.module.system.api.agent.imports.AgentImportPreflightRespVO;
|
import cn.iocoder.yudao.module.system.api.agent.imports.AgentImportRowReceipt;
|
import cn.iocoder.yudao.module.system.framework.agent.AgentPrincipal;
|
import org.junit.jupiter.api.BeforeEach;
|
import org.junit.jupiter.api.Test;
|
import org.springframework.test.util.ReflectionTestUtils;
|
|
import java.math.BigDecimal;
|
import java.util.LinkedHashMap;
|
import java.util.List;
|
import java.util.Map;
|
|
import static org.junit.jupiter.api.Assertions.*;
|
import static org.mockito.ArgumentMatchers.any;
|
import static org.mockito.Mockito.*;
|
|
class MesBomImportAdapterTest {
|
|
private static final AgentPrincipal PRINCIPAL = new AgentPrincipal(1L, 1L, "live");
|
|
private MesBomImportAdapter adapter;
|
private MesMdItemService itemService;
|
private MesMdProductBomService productBomService;
|
private MesMdProductBomMapper productBomMapper;
|
|
@BeforeEach
|
void setUp() {
|
adapter = new MesBomImportAdapter();
|
itemService = mock(MesMdItemService.class);
|
productBomService = mock(MesMdProductBomService.class);
|
productBomMapper = mock(MesMdProductBomMapper.class);
|
ReflectionTestUtils.setField(adapter, "itemService", itemService);
|
ReflectionTestUtils.setField(adapter, "productBomService", productBomService);
|
ReflectionTestUtils.setField(adapter, "productBomMapper", productBomMapper);
|
when(itemService.getItemByCode("P")).thenReturn(item(1L, "P"));
|
when(itemService.getItemByCode("C")).thenReturn(item(2L, "C"));
|
when(itemService.getItemByCode("A")).thenReturn(item(3L, "A"));
|
when(itemService.getItemByCode("X")).thenReturn(null);
|
when(productBomMapper.selectAll()).thenReturn(List.of());
|
}
|
|
@Test
|
void preflightCreatesWhenItemsAreSynced() {
|
AgentImportPreflightRespVO plan = adapter.preflight(PRINCIPAL, request(row("r1", "P", "C", "2")));
|
|
assertEquals("CREATE", plan.getRows().get(0).getAction());
|
assertEquals(1, plan.getSummary().getCreate());
|
assertTrue(plan.getCanCommit());
|
assertNotNull(plan.getPreflightHash());
|
}
|
|
@Test
|
void existingCombinationIsSkippedWithWarning() {
|
when(productBomMapper.selectAll()).thenReturn(List.of(bom(50L, 1L, 2L)));
|
|
AgentImportPreflightRespVO plan = adapter.preflight(PRINCIPAL, request(row("r1", "P", "C", "2")));
|
|
assertEquals("SKIP", plan.getRows().get(0).getAction());
|
assertEquals(50L, plan.getRows().get(0).getTargetId());
|
assertEquals(1, plan.getSummary().getSkip());
|
assertTrue(plan.getRows().get(0).getWarnings().stream()
|
.anyMatch(item -> "BOM_EXISTS".equals(item.getCode())));
|
}
|
|
@Test
|
void unsyncedComponentBlocksRow() {
|
AgentImportPreflightRespVO plan = adapter.preflight(PRINCIPAL, request(row("r1", "P", "X", "1")));
|
|
assertEquals("BLOCKED", plan.getRows().get(0).getAction());
|
assertTrue(plan.getRows().get(0).getBlockers().stream()
|
.anyMatch(item -> "MES_ITEM_NOT_SYNCED".equals(item.getCode())));
|
assertFalse(plan.getCanCommit());
|
}
|
|
@Test
|
void selfReferenceBlocksRow() {
|
AgentImportPreflightRespVO plan = adapter.preflight(PRINCIPAL, request(row("r1", "P", "P", "1")));
|
|
assertEquals("BLOCKED", plan.getRows().get(0).getAction());
|
assertTrue(plan.getRows().get(0).getBlockers().stream()
|
.anyMatch(item -> "BOM_SELF_REFERENCE".equals(item.getCode())));
|
}
|
|
@Test
|
void duplicateCombinationInFileBlocksSecondRow() {
|
AgentImportPreflightRespVO plan = adapter.preflight(PRINCIPAL, request(
|
row("r1", "P", "C", "1"),
|
row("r2", "P", "C", "2")));
|
|
assertEquals("CREATE", plan.getRows().get(0).getAction());
|
assertEquals("BLOCKED", plan.getRows().get(1).getAction());
|
assertTrue(plan.getRows().get(1).getBlockers().stream()
|
.anyMatch(item -> "DUPLICATE_IN_FILE".equals(item.getCode())));
|
}
|
|
@Test
|
void cycleAgainstExistingGraphBlocksRow() {
|
when(productBomMapper.selectAll()).thenReturn(List.of(bom(60L, 3L, 1L)));
|
|
AgentImportPreflightRespVO plan = adapter.preflight(PRINCIPAL, request(row("r1", "P", "A", "1")));
|
|
assertEquals("BLOCKED", plan.getRows().get(0).getAction());
|
assertTrue(plan.getRows().get(0).getBlockers().stream()
|
.anyMatch(item -> "BOM_CYCLE".equals(item.getCode())));
|
}
|
|
@Test
|
void invalidQuantityBlocksRow() {
|
AgentImportPreflightRespVO plan = adapter.preflight(PRINCIPAL, request(row("r1", "P", "C", "0")));
|
|
assertEquals("BLOCKED", plan.getRows().get(0).getAction());
|
assertTrue(plan.getRows().get(0).getBlockers().stream()
|
.anyMatch(item -> "INVALID_QUANTITY".equals(item.getCode())));
|
}
|
|
@Test
|
void commitCreatesBomWithResolvedItemIds() {
|
when(productBomService.createProductBom(any())).thenReturn(88L);
|
|
AgentImportRowReceipt receipt = adapter.commitRow(PRINCIPAL, new AgentImportCommitReqVO(),
|
AgentImportPreflightRespVO.Row.builder().candidateId("r1").action("CREATE").build(),
|
row("r1", "P", "C", "2"));
|
|
assertEquals(88L, receipt.targetId());
|
assertEquals("P", receipt.code());
|
verify(productBomService).createProductBom(any(MesMdProductBomSaveReqVO.class));
|
}
|
|
private static MesMdItemDO item(Long id, String code) {
|
MesMdItemDO item = new MesMdItemDO();
|
item.setId(id);
|
item.setCode(code);
|
return item;
|
}
|
|
private static MesMdProductBomDO bom(Long id, Long itemId, Long bomItemId) {
|
MesMdProductBomDO bom = new MesMdProductBomDO();
|
bom.setId(id);
|
bom.setItemId(itemId);
|
bom.setBomItemId(bomItemId);
|
bom.setQuantity(BigDecimal.ONE);
|
return bom;
|
}
|
|
private static AgentImportPreflightReqVO request(AgentImportPreflightReqVO.Row... rows) {
|
AgentImportPreflightReqVO request = new AgentImportPreflightReqVO();
|
request.setAttachmentId(1L);
|
request.setSourceSha256("a".repeat(64));
|
request.setProposalRevision("0");
|
request.setRows(List.of(rows));
|
return request;
|
}
|
|
private static AgentImportPreflightReqVO.Row row(String candidateId, String parent, String component,
|
String quantity) {
|
Map<String, String> values = new LinkedHashMap<>();
|
values.put("parentCode", parent);
|
values.put("componentCode", component);
|
values.put("quantity", quantity);
|
AgentImportPreflightReqVO.Row row = new AgentImportPreflightReqVO.Row();
|
row.setCandidateId(candidateId);
|
row.setRowNo(1);
|
row.setValues(values);
|
return row;
|
}
|
}
|