diff --git a/lastleg-service/src/main/java/com/baiyue/lastleg/dispatch/entity/DispatchPalletLock.java b/lastleg-service/src/main/java/com/baiyue/lastleg/dispatch/entity/DispatchPalletLock.java index a62da4a4d..57239e4ed 100644 --- a/lastleg-service/src/main/java/com/baiyue/lastleg/dispatch/entity/DispatchPalletLock.java +++ b/lastleg-service/src/main/java/com/baiyue/lastleg/dispatch/entity/DispatchPalletLock.java @@ -24,6 +24,7 @@ public class DispatchPalletLock { private Long planPalletId; private Long warehousePalletId; private Long dispatchOrderId; + @TableField(updateStrategy = FieldStrategy.ALWAYS) private Long draftContainerId; @TableField(updateStrategy = FieldStrategy.ALWAYS) private String draftToken; diff --git a/lastleg-service/src/main/java/com/baiyue/lastleg/dispatch/mapper/DispatchPalletLockMapper.java b/lastleg-service/src/main/java/com/baiyue/lastleg/dispatch/mapper/DispatchPalletLockMapper.java index 38ed3c93d..5d849f04b 100644 --- a/lastleg-service/src/main/java/com/baiyue/lastleg/dispatch/mapper/DispatchPalletLockMapper.java +++ b/lastleg-service/src/main/java/com/baiyue/lastleg/dispatch/mapper/DispatchPalletLockMapper.java @@ -7,8 +7,16 @@ import org.apache.ibatis.annotations.Param; import org.apache.ibatis.annotations.Select; import org.apache.ibatis.annotations.Update; +import java.util.List; + @Mapper public interface DispatchPalletLockMapper extends BaseMapper { + @Select("SELECT * FROM ll_dispatch_pallet_lock WHERE draft_token=#{draftToken} " + + "AND draft_container_id=#{draftContainerId} AND status='ACTIVE' " + + "AND (expires_at IS NULL OR expires_at>CURRENT_TIMESTAMP(3)) ORDER BY locked_at,id") + List findActiveByDraftContainer(@Param("draftToken") String draftToken, + @Param("draftContainerId") Long draftContainerId); + @Select("SELECT * FROM ll_dispatch_pallet_lock WHERE customer_id=#{customerId} AND source_pallet_key=#{sourcePalletKey} " + "AND status='ACTIVE' LIMIT 1 FOR UPDATE") DispatchPalletLock lockActive(@Param("customerId") String customerId, diff --git a/lastleg-service/src/main/java/com/baiyue/lastleg/dispatch/service/DispatchService.java b/lastleg-service/src/main/java/com/baiyue/lastleg/dispatch/service/DispatchService.java index 984896219..b41154dda 100644 --- a/lastleg-service/src/main/java/com/baiyue/lastleg/dispatch/service/DispatchService.java +++ b/lastleg-service/src/main/java/com/baiyue/lastleg/dispatch/service/DispatchService.java @@ -95,7 +95,8 @@ public class DispatchService { private List containers(String token) { return draftContainers.findByToken(token).stream().map(c -> new DispatchContainerResponse(String.valueOf(c.getId()), c.getCapacity(), - locks.selectList(new LambdaQueryWrapper().eq(DispatchPalletLock::getDraftContainerId, c.getId()).eq(DispatchPalletLock::getStatus, "ACTIVE")).stream().map(x -> String.valueOf(x.getPlanPalletId())).toList())).toList(); + locks.findActiveByDraftContainer(token, c.getId()).stream() + .map(x -> String.valueOf(x.getPlanPalletId())).toList())).toList(); } @Transactional @@ -274,6 +275,7 @@ public class DispatchService { if (draftToken != null) { requireDraftOwner(lock, operatorId, draftToken); lock.setDispatchOrderId(dispatch.getId()); + lock.setDraftContainerId(null); lock.setDraftToken(null); lock.setExpiresAt(null); lock.setUpdatedAt(now); @@ -335,6 +337,17 @@ public class DispatchService { pdaTask.setCreatedAt(now); pdaTask.setUpdatedAt(now); pdaTasks.insert(pdaTask); + if (draftToken != null) { + draftContainers.delete(new LambdaQueryWrapper() + .eq(DispatchDraftContainer::getDraftToken, draftToken)); + DispatchDraft draft = drafts.lockActive(draftToken, trimToNull(operatorId)); + if (draft != null) { + draft.setStatus("RELEASED"); + draft.setReleasedAt(now); + draft.setUpdatedAt(now); + drafts.updateById(draft); + } + } return response(dispatch, items.findByDispatchOrder(customerId, dispatch.getId())); } diff --git a/lastleg-service/src/test/java/com/baiyue/lastleg/dispatch/service/DispatchServiceTest.java b/lastleg-service/src/test/java/com/baiyue/lastleg/dispatch/service/DispatchServiceTest.java index 9e4c36eef..15669c6d1 100644 --- a/lastleg-service/src/test/java/com/baiyue/lastleg/dispatch/service/DispatchServiceTest.java +++ b/lastleg-service/src/test/java/com/baiyue/lastleg/dispatch/service/DispatchServiceTest.java @@ -4,6 +4,8 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baiyue.lastleg.dispatch.dto.DispatchRequests; import com.baiyue.lastleg.dispatch.dto.DispatchResponse; +import com.baiyue.lastleg.dispatch.entity.DispatchDraft; +import com.baiyue.lastleg.dispatch.entity.DispatchDraftContainer; import com.baiyue.lastleg.dispatch.entity.DispatchItem; import com.baiyue.lastleg.dispatch.entity.DispatchOrder; import com.baiyue.lastleg.dispatch.entity.DispatchPalletLock; @@ -32,6 +34,7 @@ import java.time.LocalDateTime; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.eq; @@ -160,15 +163,41 @@ class DispatchServiceTest { void preArrangeConvertsOwnedDraftLockInsteadOfInsertingAnotherLock() { when(candidates.lockSelected("100", List.of(10L))).thenReturn(List.of(candidate(10L, null, "ONT8"))); DispatchPalletLock lock = new DispatchPalletLock(); - lock.setDraftToken("draft-1"); lock.setOperatorId("7"); lock.setStatus("ACTIVE"); lock.setActiveKey("PLAN:10"); + lock.setDraftToken("draft-1"); lock.setDraftContainerId(21L); lock.setOperatorId("7"); lock.setStatus("ACTIVE"); lock.setActiveKey("PLAN:10"); + DispatchDraft draft = new DispatchDraft(); + draft.setId(31L); draft.setDraftToken("draft-1"); draft.setOperatorId("7"); draft.setStatus("ACTIVE"); when(locks.lockActive("100", "PLAN:10")).thenReturn(lock); + when(drafts.lockActive("draft-1", "7")).thenReturn(draft); service.preArrange("100", "7", new DispatchRequests.PreArrange(List.of(10L), null, null, null, null, "draft-1")); assertNotNull(lock.getDispatchOrderId()); - assertEquals(null, lock.getDraftToken()); + assertNull(lock.getDraftToken()); + assertNull(lock.getDraftContainerId()); + assertEquals("RELEASED", draft.getStatus()); + assertNotNull(draft.getReleasedAt()); verify(locks).updateById(lock); verify(locks, never()).insert(any(DispatchPalletLock.class)); + verify(draftContainers).delete(any(LambdaQueryWrapper.class)); + verify(drafts).updateById(draft); + } + + @Test + void activeDraftOnlyRestoresLocksStillOwnedByThatDraft() { + DispatchDraft draft = new DispatchDraft(); + draft.setDraftToken("draft-1"); draft.setOperatorId("7"); draft.setStatus("ACTIVE"); + DispatchDraftContainer container = new DispatchDraftContainer(); + container.setId(21L); container.setDraftToken("draft-1"); container.setCapacity(12); + DispatchPalletLock owned = new DispatchPalletLock(); + owned.setPlanPalletId(10L); owned.setDraftToken("draft-1"); owned.setDraftContainerId(21L); + when(drafts.findActiveByOperator("7")).thenReturn(List.of(draft)); + when(draftContainers.findByToken("draft-1")).thenReturn(List.of(container)); + when(locks.findActiveByDraftContainer("draft-1", 21L)).thenReturn(List.of(owned)); + + var result = service.activeDrafts("7"); + + assertEquals(List.of("10"), result.get(0).containers().get(0).palletIds()); + verify(locks).findActiveByDraftContainer("draft-1", 21L); } @Test