package com.zy.asrs.service.impl; import com.baomidou.mybatisplus.mapper.EntityWrapper; import com.baomidou.mybatisplus.service.impl.ServiceImpl; import com.core.common.Cools; import com.core.common.R; import com.core.common.SnowflakeIdWorker; import com.core.exception.CoolException; import com.zy.asrs.entity.BasAreas; import com.zy.asrs.entity.LocCache; import com.zy.asrs.entity.param.LocMastInitParam; import com.zy.asrs.mapper.LocCacheMapper; import com.zy.asrs.service.BasAreasService; import com.zy.asrs.service.LocCacheService; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.util.ArrayList; import java.util.Arrays; import java.util.Date; import java.util.List; @Slf4j @Service("locCacheService") public class LocCacheServiceImpl extends ServiceImpl implements LocCacheService { @Autowired private BasAreasService basAreasService; @Autowired private SnowflakeIdWorker snowflakeIdWorker; /** * @author Ryan * @date 2025/9/18 * @description: 初始化库区库位信息 * @version 1.0 */ @Override public R initLocCache(LocMastInitParam param, Long userId) { try { List list = new ArrayList<>(); BasAreas areas = basAreasService.selectById(param.getIdentifying()); if (Cools.isEmpty(areas)) { return R.error("库区不存在!!!"); } for (int r = param.getStartRow(); r <= param.getEndRow(); r++) { for (int b = param.getStartBay(); b <= param.getEndBay(); b++) { for (int l = param.getStartLev(); l <= param.getEndLev(); l++) { // 获取库位号 String locNo = areas.getAreaNo() + String.format("%02d", r) + String.format("%03d", b) + String.format("%02d", l); Date now = new Date(); LocCache locMast = new LocCache(); // 手动生成ID locMast.setId(snowflakeIdWorker.nextId()); locMast.setLocNo(locNo); locMast.setLocSts("O"); locMast.setRow1(r); // 排 locMast.setBay1(b); // 列 locMast.setLev1(l); // 层 locMast.setLocType1(!Cools.isEmpty(param.getLocType1()) ? param.getLocType1() : 1); locMast.setLocType2(param.getLocType2()); locMast.setLocType3(param.getLocType3()); locMast.setAppeUser(userId); locMast.setAppeTime(now); locMast.setModiUser(userId); locMast.setModiTime(now); locMast.setAreaId(areas.getId()); locMast.setAreaName(areas.getName()); list.add(locMast); } } } if (!Cools.isEmpty(param.getEnable()) && param.getEnable() == 1) { if (!this.delete(new EntityWrapper<>())) { throw new CoolException("删除失败!!"); } } // SQL Server 批量插入获取生成键可能失败,改用循环单条插入确保所有记录都能成功插入 int successCount = 0; for (LocCache locCache : list) { if (this.insert(locCache)) { successCount++; } else { log.error("插入库位失败: {}", locCache.getLocNo()); } } if (successCount != list.size()) { throw new CoolException(String.format("添加失败!成功插入 %d 条,应插入 %d 条", successCount, list.size())); } return R.ok("初始化成功,共插入 " + successCount + " 条记录"); } catch (Exception e) { log.error("初始化库位失败", e); return R.error("初始化失败===>" + e.getMessage()); } } /** * 锁定/解锁缓存库位(复用AGV搬货后的库位有货逻辑) * 锁定:满托设置为 "F"(在库),空托设置为 "D"(空桶/空栈板) * 解锁:统一设置为 "O"(空库位) * @param locNo 库位号 * @param lock 是否锁定,true-锁定,false-解锁 * @param fullPlt 是否满托,true-满托(设置为F),false-空托(设置为D),解锁时忽略此参数 * @param userId 用户ID * @return 操作结果 */ @Override public R lockOrUnlockLocCache(String locNo, Boolean lock, Boolean fullPlt, Long userId) { try { if (Cools.isEmpty(locNo)) { return R.error("库位号不能为空"); } // 根据库位号查询库位 EntityWrapper wrapper = new EntityWrapper<>(); wrapper.eq("loc_no", locNo); LocCache locCache = this.selectOne(wrapper); if (Cools.isEmpty(locCache)) { return R.error("库位不存在:" + locNo); } // 更新库位状态 String locSts; if (lock) { // 锁定:满托设置为"F"(在库),空托设置为"D"(空桶/空栈板) if (fullPlt == null) { return R.error("锁定操作时,满托参数不能为空"); } locSts = fullPlt ? "F" : "D"; locCache.setFullPlt(fullPlt ? "Y" : "N"); } else { // 解锁:统一设置为"O"(空库位) locSts = "O"; locCache.setFullPlt("N"); } locCache.setLocSts(locSts); locCache.setModiUser(userId); locCache.setModiTime(new Date()); boolean success = this.updateById(locCache); if (success) { String action = lock ? "锁定" : "解锁"; String detail = lock ? (fullPlt ? "满托" : "空托") : ""; log.info("{}库位成功:{},库位状态:{},{},操作人:{}", action, locNo, locCache.getLocSts(), detail, userId); return R.ok(action + "成功"); } else { return R.error("操作失败"); } } catch (Exception e) { log.error("锁定/解锁库位失败", e); return R.error("操作失败:" + e.getMessage()); } } /** * 锁定/解锁当前排的所有库位 * @param locNo 库位号(用于获取排号) * @param lock 是否锁定,true-锁定,false-解锁 * @param userId 用户ID * @return 操作结果 */ @Override public R lockOrUnlockRowLocCache(String locNo, Boolean lock, Boolean fullPlt, Long userId) { try { if (Cools.isEmpty(locNo)) { return R.error("库位号不能为空"); } // 根据库位号查询库位,获取排号 EntityWrapper wrapper = new EntityWrapper<>(); wrapper.eq("loc_no", locNo); LocCache locCache = this.selectOne(wrapper); if (Cools.isEmpty(locCache)) { return R.error("库位不存在:" + locNo); } Integer row = locCache.getRow1(); if (Cools.isEmpty(row)) { return R.error("库位排号为空:" + locNo); } // 查询当前排的1、2、3列的所有库位(解锁整排时只清空1、2、3列) EntityWrapper rowWrapper = new EntityWrapper<>(); rowWrapper.eq("row1", row) .in("bay1", Arrays.asList(1, 2, 3)); // 只查询1、2、3列 // 如果库位有库区ID,也加上库区条件 if (!Cools.isEmpty(locCache.getAreaId())) { rowWrapper.eq("area_id", locCache.getAreaId()); } List locCacheList = this.selectList(rowWrapper); if (Cools.isEmpty(locCacheList)) { return R.error("当前排没有找到库位"); } // 批量更新库位状态 Date now = new Date(); int successCount = 0; String locSts; if (lock) { // 锁定:满托设置为"F"(在库),空托设置为"D"(空桶/空栈板) if (fullPlt == null) { return R.error("锁定操作时,满托参数不能为空"); } locSts = fullPlt ? "F" : "D"; } else { // 解锁:统一设置为"O"(空库位) locSts = "O"; } for (LocCache cache : locCacheList) { cache.setLocSts(locSts); if (lock) { cache.setFullPlt(fullPlt ? "Y" : "N"); } else { cache.setFullPlt("N"); } cache.setModiUser(userId); cache.setModiTime(now); if (this.updateById(cache)) { successCount++; } } String action = lock ? "锁定" : "解锁"; log.info("{}排{}所有库位成功,共{}个库位,操作人:{}", action, row, successCount, userId); return R.ok(String.format("%s成功,共处理 %d 个库位", action, successCount)); } catch (Exception e) { log.error("锁定/解锁排库位失败", e); return R.error("操作失败:" + e.getMessage()); } } /** * 锁定/解锁当前列的所有库位 * @param locNo 库位号(用于获取列号bay1) * @param lock 是否锁定,true-锁定,false-解锁 * @param fullPlt 是否满托,true-满托(设置为F),false-空托(设置为D),解锁时忽略此参数 * @param userId 用户ID * @return 操作结果 */ @Override public R lockOrUnlockBayLocCache(String locNo, Boolean lock, Boolean fullPlt, Long userId) { try { if (Cools.isEmpty(locNo)) { return R.error("库位号不能为空"); } // 根据库位号查询库位,获取列号 EntityWrapper wrapper = new EntityWrapper<>(); wrapper.eq("loc_no", locNo); LocCache locCache = this.selectOne(wrapper); if (Cools.isEmpty(locCache)) { return R.error("库位不存在:" + locNo); } Integer bay = locCache.getBay1(); if (Cools.isEmpty(bay)) { return R.error("库位列号为空:" + locNo); } // 查询当前列的所有库位 EntityWrapper bayWrapper = new EntityWrapper<>(); bayWrapper.eq("bay1", bay); // 如果库位有库区ID,也加上库区条件 if (!Cools.isEmpty(locCache.getAreaId())) { bayWrapper.eq("area_id", locCache.getAreaId()); } List locCacheList = this.selectList(bayWrapper); if (Cools.isEmpty(locCacheList)) { return R.error("当前列没有找到库位"); } // 批量更新库位状态 Date now = new Date(); int successCount = 0; String locSts; if (lock) { // 锁定:满托设置为"F"(在库),空托设置为"D"(空桶/空栈板) if (fullPlt == null) { return R.error("锁定操作时,满托参数不能为空"); } locSts = fullPlt ? "F" : "D"; } else { // 解锁:统一设置为"O"(空库位) locSts = "O"; } for (LocCache cache : locCacheList) { cache.setLocSts(locSts); if (lock) { cache.setFullPlt(fullPlt ? "Y" : "N"); } else { cache.setFullPlt("N"); } cache.setModiUser(userId); cache.setModiTime(now); if (this.updateById(cache)) { successCount++; } } String action = lock ? "锁定" : "解锁"; log.info("{}列{}所有库位成功,共{}个库位,操作人:{}", action, bay, successCount, userId); return R.ok(String.format("%s成功,共处理 %d 个库位", action, successCount)); } catch (Exception e) { log.error("锁定/解锁列库位失败", e); return R.error("操作失败:" + e.getMessage()); } } /** * 清空整排的所有库位(所有列) * @param locNo 库位号(用于获取排号row1) * @param lock 是否锁定,true-锁定,false-解锁(清空) * @param fullPlt 是否满托,true-满托(设置为F),false-空托(设置为D),解锁时忽略此参数 * @param userId 用户ID * @return 操作结果 */ @Override public R clearAllColumnsInRow(String locNo, Boolean lock, Boolean fullPlt, Long userId) { try { if (Cools.isEmpty(locNo)) { return R.error("库位号不能为空"); } // 根据库位号查询库位,获取排号 EntityWrapper wrapper = new EntityWrapper<>(); wrapper.eq("loc_no", locNo); LocCache locCache = this.selectOne(wrapper); if (Cools.isEmpty(locCache)) { return R.error("库位不存在:" + locNo); } Integer row = locCache.getRow1(); if (Cools.isEmpty(row)) { return R.error("库位排号为空:" + locNo); } // 查询当前排的所有库位(所有列,不限制bay1) EntityWrapper rowWrapper = new EntityWrapper<>(); rowWrapper.eq("row1", row); // 如果库位有库区ID,也加上库区条件 if (!Cools.isEmpty(locCache.getAreaId())) { rowWrapper.eq("area_id", locCache.getAreaId()); } List locCacheList = this.selectList(rowWrapper); if (Cools.isEmpty(locCacheList)) { return R.error("当前排没有找到库位"); } // 批量更新库位状态 Date now = new Date(); int successCount = 0; String locSts; if (lock) { // 锁定:满托设置为"F"(在库),空托设置为"D"(空桶/空栈板) if (fullPlt == null) { return R.error("锁定操作时,满托参数不能为空"); } locSts = fullPlt ? "F" : "D"; } else { // 解锁:统一设置为"O"(空库位) locSts = "O"; } for (LocCache cache : locCacheList) { cache.setLocSts(locSts); if (lock) { cache.setFullPlt(fullPlt ? "Y" : "N"); } else { cache.setFullPlt("N"); } cache.setModiUser(userId); cache.setModiTime(now); if (this.updateById(cache)) { successCount++; } } String action = lock ? "锁定" : "清空"; log.info("{}排{}所有库位(所有列)成功,共{}个库位,操作人:{}", action, row, successCount, userId); return R.ok(String.format("%s成功,共处理 %d 个库位", action, successCount)); } catch (Exception e) { log.error("清空整排库位失败", e); return R.error("操作失败:" + e.getMessage()); } } }