package com.ruoyi.pda.service; import com.ruoyi.in.stockindetail.domain.InStockinDetail; import com.ruoyi.in.stockindetail.service.IInStockinDetailService; import com.ruoyi.job.mydojob.domain.MydoJob; import com.ruoyi.job.mydojob.mapper.MydoJobMapper; import com.ruoyi.stock.stock.domain.BasStock; import com.ruoyi.stock.stock.mapper.BasStockMapper; import org.apache.ibatis.builder.xml.XMLMapperBuilder; import org.apache.ibatis.mapping.Environment; import org.apache.ibatis.session.Configuration; import org.apache.ibatis.session.SqlSession; import org.apache.ibatis.session.SqlSessionFactory; import org.apache.ibatis.session.SqlSessionFactoryBuilder; import org.apache.ibatis.transaction.jdbc.JdbcTransactionFactory; import org.h2.jdbcx.JdbcDataSource; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.NullAndEmptySource; import org.junit.jupiter.params.provider.ValueSource; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.test.util.ReflectionTestUtils; import java.util.List; import java.util.UUID; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; class HalfTrayEligibilityTest { private JdbcTemplate jdbc; private SqlSessionFactory sessions; @BeforeEach void setUp() throws Exception { JdbcDataSource dataSource = new JdbcDataSource(); dataSource.setURL("jdbc:h2:mem:" + UUID.randomUUID() + ";MODE=MSSQLServer;DB_CLOSE_DELAY=-1"); jdbc = new JdbcTemplate(dataSource); jdbc.execute("create table mydo_job(job_id varchar(80), in_or_out varchar(20))"); jdbc.execute("create table mydo_job_detail(job_id varchar(80), spare4 varchar(80), exit_id varchar(80))"); Configuration configuration = new Configuration(new Environment("test", new JdbcTransactionFactory(), dataSource)); configuration.getTypeAliasRegistry().registerAlias("MydoJob", MydoJob.class); configuration.getTypeAliasRegistry().registerAlias("InStockinDetail", InStockinDetail.class); try (var stream = getClass().getClassLoader().getResourceAsStream("mapper/job/MydoJobMapper.xml")) { new XMLMapperBuilder(stream, configuration, "mapper/job/MydoJobMapper.xml", configuration.getSqlFragments()).parse(); } sessions = new SqlSessionFactoryBuilder().build(configuration); } @AfterEach void close() { jdbc.execute("shutdown"); } @ParameterizedTest @NullAndEmptySource @ValueSource(strings = {" "}) void blankCodeDoesNotHideCandidatesForAnUnrelatedProject(String cargoNo) { job("HPC202609070029", "26", "AD.A-00002.01.26", cargoNo); InStockinDetail detail = incoming("AD.A-00002.01.32", cargoNo); IInStockinDetailService inbound = mock(IInStockinDetailService.class); BasStockMapper stocks = mock(BasStockMapper.class); when(inbound.selectInStockinDetailByStockinDetailId("5673093")).thenReturn(detail); BasStock tray333 = new BasStock(); tray333.setTrayCode("T0000333"); BasStock tray343 = new BasStock(); tray343.setTrayCode("T0000343"); when(stocks.selectHasHalfTray(detail)).thenReturn(List.of(tray333, tray343)); try (SqlSession session = sessions.openSession()) { PdaServiceImp service = new PdaServiceImp(); ReflectionTestUtils.setField(service, "inStockinDetailService", inbound); ReflectionTestUtils.setField(service, "basStockMapper", stocks); ReflectionTestUtils.setField(service, "mapper", session.getMapper(MydoJobMapper.class)); assertThat(service.selectHasHalfTray("5673093")) .extracting(BasStock::getTrayCode).containsExactly("T0000333", "T0000343"); } } @ParameterizedTest @NullAndEmptySource @ValueSource(strings = {" "}) void sameProjectRemainsBlockedEvenWhenCodeIsBlank(String cargoNo) { job("SAME-PROJECT", "26", "PROJECT", "OTHER-CODE"); assertThat(count(incoming("PROJECT", cargoNo))).isEqualTo(1); } @Test void sameNonemptyCodeStillBlocksAcrossProjectsAndCountsAJobOnlyOnce() { job("SAME-CODE", "26", "OTHER-PROJECT", "020210100000249"); jdbc.update("insert into mydo_job_detail values(?,?,?)", "SAME-CODE", "OTHER-PROJECT", "020210100000249"); assertThat(count(incoming("PROJECT", "020210100000249"))).isEqualTo(1); } @Test void differentNonemptyCodeDoesNotBlock() { job("UNRELATED", "26", "OTHER-PROJECT", "OTHER-CODE"); assertThat(count(incoming("PROJECT", "CODE"))).isZero(); } @Test void nonHalfTrayJobsAndOrphanDetailsDoNotBlock() { job("NORMAL-OUT", "21", "PROJECT", "CODE"); jdbc.update("insert into mydo_job_detail values(?,?,?)", "COMPLETED-JOB", "PROJECT", "CODE"); assertThat(count(incoming("PROJECT", "CODE"))).isZero(); } @Test void blankProjectDoesNotCreateAnotherEmptyIdentityMatch() { job("NO-PROJECT", "26", "", "OTHER-CODE"); assertThat(count(incoming("", "CODE"))).isZero(); assertThat(count(incoming("", ""))).isZero(); } private int count(InStockinDetail detail) { try (SqlSession session = sessions.openSession()) { return session.getMapper(MydoJobMapper.class).selectBySpare4OrCargo(detail); } } private void job(String id, String type, String project, String code) { jdbc.update("insert into mydo_job values(?,?)", id, type); jdbc.update("insert into mydo_job_detail values(?,?,?)", id, project, code); } private InStockinDetail incoming(String project, String code) { InStockinDetail detail = new InStockinDetail(); detail.setSpare4(project); detail.setCargoNo(code); return detail; } }