| | |
| | | import cn.hutool.core.util.IdUtil; |
| | | import cn.hutool.core.util.StrUtil; |
| | | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| | | import cn.iocoder.yudao.module.mes.controller.admin.pro.bagcode.vo.MesProBagCodeBindBatchReqVO; |
| | | import cn.iocoder.yudao.module.mes.controller.admin.pro.bagcode.vo.MesProBagCodeBindReqVO; |
| | | import cn.iocoder.yudao.module.mes.controller.admin.pro.bagcode.vo.MesProBagCodeGenerateReqVO; |
| | | import cn.iocoder.yudao.module.mes.controller.admin.pro.bagcode.vo.MesProBagCodeGenerateRespVO; |
| | | import cn.iocoder.yudao.module.mes.controller.admin.pro.bagcode.vo.MesProBagCodePageReqVO; |
| | | import cn.iocoder.yudao.module.mes.controller.admin.pro.bagcode.vo.MesProBagCodeReplaceItemRespVO; |
| | | import cn.iocoder.yudao.module.mes.controller.admin.pro.bagcode.vo.MesProBagCodeReplaceReqVO; |
| | |
| | | |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public String generateBagCodes(MesProBagCodeGenerateReqVO generateReqVO) { |
| | | // 1. 校验批次存在且处于生产中状态 |
| | | MesProBatchDO batch = batchMapper.selectByIdForUpdate(generateReqVO.getBatchId()); |
| | | if (batch == null) { |
| | | throw exception(PRO_BATCH_NOT_EXISTS); |
| | | } |
| | | if (!MesProBatchStatusEnum.PRODUCING.getStatus().equals(batch.getStatus())) { |
| | | throw exception(PRO_BATCH_STATUS_NOT_GENERATE_CODE); |
| | | } |
| | | public MesProBagCodeGenerateRespVO generateBagCodes(MesProBagCodeGenerateReqVO generateReqVO) { |
| | | if (generateReqVO.getCount() == null || generateReqVO.getCount() <= 0) { |
| | | throw exception(PRO_BAG_CODE_GENERATE_COUNT_INVALID); |
| | | } |
| | | |
| | | // 2. 计算起始序号(包含已逻辑删除记录,保证序号不回退、码值唯一) |
| | | int startNo = bagCodeMapper.selectMaxBagNo(batch.getId()) + 1; |
| | | |
| | | // 3. 批量生成袋码:批次号 + - + 4 位袋序号,同一次生成共享同一 UUID(数据包) |
| | | // 生成阶段只创建全局唯一袋码,生产批次在后续录入 |
| | | int startNo = bagCodeMapper.selectMaxBagNo() + 1; |
| | | String uuid = IdUtil.fastSimpleUUID(); |
| | | List<MesProBagCodeDO> bagCodes = new ArrayList<>(generateReqVO.getCount()); |
| | | for (int i = 0; i < generateReqVO.getCount(); i++) { |
| | | int bagNo = startNo + i; |
| | | bagCodes.add(new MesProBagCodeDO() |
| | | .setUuid(uuid) |
| | | .setCode(batch.getCode() + "-" + StrUtil.padPre(String.valueOf(bagNo), 4, '0')) |
| | | .setCode("BAG-" + StrUtil.padPre(String.valueOf(bagNo), 8, '0')) |
| | | .setBagNo(bagNo) |
| | | .setBatchId(batch.getId()) |
| | | .setBatchCode(batch.getCode()) |
| | | .setStatus(MesProBagCodeStatusEnum.GENERATED.getStatus()) |
| | | .setRemark(generateReqVO.getRemark())); |
| | | } |
| | | bagCodeMapper.insertBatch(bagCodes); |
| | | return new MesProBagCodeGenerateRespVO().setUuid(uuid); |
| | | } |
| | | |
| | | // 4. 回写批次袋码数量 |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public void bindBatch(MesProBagCodeBindBatchReqVO bindReqVO) { |
| | | MesProBatchDO batch = batchMapper.selectByIdForUpdate(bindReqVO.getBatchId()); |
| | | if (batch == null) { |
| | | throw exception(PRO_BATCH_NOT_EXISTS); |
| | | } |
| | | if (!MesProBatchStatusEnum.PRODUCING.getStatus().equals(batch.getStatus())) { |
| | | throw exception(PRO_BATCH_STATUS_NOT_GENERATE_CODE); |
| | | } |
| | | // 临时批次(未补录正式批次号)不允许袋码录入 |
| | | if (StrUtil.isEmpty(batch.getCode())) { |
| | | throw exception(PRO_BATCH_NOT_FILLED); |
| | | } |
| | | List<Long> ids = bindReqVO.getIds().stream().distinct().toList(); |
| | | List<MesProBagCodeDO> bagCodes = bagCodeMapper.selectListByIdsForUpdate(ids); |
| | | if (bagCodes.size() != ids.size() || bagCodes.stream().anyMatch(code -> |
| | | code.getBatchId() != null || !MesProBagCodeStatusEnum.GENERATED.getStatus().equals(code.getStatus()))) { |
| | | throw exception(PRO_BAG_CODE_STATUS_NOT_GENERATED); |
| | | } |
| | | if (bagCodeMapper.bindBatchByIds(ids, batch.getId(), batch.getCode(), |
| | | MesProBagCodeStatusEnum.GENERATED.getStatus()) != ids.size()) { |
| | | throw exception(PRO_BAG_CODE_STATUS_NOT_GENERATED); |
| | | } |
| | | batchMapper.updateById(new MesProBatchDO().setId(batch.getId()) |
| | | .setBagQuantity((batch.getBagQuantity() == null ? 0 : batch.getBagQuantity()) |
| | | + generateReqVO.getCount())); |
| | | return uuid; |
| | | .setBagQuantity(bagCodeMapper.selectEffectiveCountByBatchId(batch.getId()))); |
| | | } |
| | | |
| | | @Override |
| | |
| | | |
| | | String replaceUuid = IdUtil.fastSimpleUUID(); |
| | | LocalDateTime replaceTime = LocalDateTime.now(); |
| | | int startNo = bagCodeMapper.selectMaxBagNo(batch.getId()) + 1; |
| | | int startNo = bagCodeMapper.selectMaxBagNo() + 1; |
| | | List<MesProBagCodeDO> newBagCodes = new ArrayList<>(oldBagCodes.size()); |
| | | List<MesProBagCodeReplaceDO> replacements = new ArrayList<>(oldBagCodes.size()); |
| | | List<MesProBagCodeReplaceItemRespVO> items = new ArrayList<>(oldBagCodes.size()); |
| | |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public void bindPallet(MesProBagCodeBindReqVO bindReqVO) { |
| | | // 1. 校验托盘存在 |
| | | MesProPalletDO pallet = palletService.validatePalletExists(bindReqVO.getPalletId()); |
| | | // 2. 校验袋码 |
| | | List<MesProBagCodeDO> bagCodes = validateBagCodesForBind(bindReqVO.getIds(), pallet); |
| | | // 1. 锁定托盘,避免与自动归集并发修改袋数 |
| | | MesProPalletDO pallet = palletMapper.selectByIdForUpdate(bindReqVO.getPalletId()); |
| | | if (pallet == null) { |
| | | throw exception(PRO_PALLET_NOT_EXISTS); |
| | | } |
| | | // 2. 锁定并校验袋码 |
| | | List<MesProBagCodeDO> bagCodes = validateBagCodesForBind(bindReqVO.getIds(), pallet, true); |
| | | // 3. 校验不超过托盘可装袋数 |
| | | int currentCount = pallet.getBagCount() == null ? 0 : pallet.getBagCount(); |
| | | if (pallet.getCapacity() != null && pallet.getCapacity() > 0 |
| | |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public void unbindPallet(MesProBagCodeBindReqVO bindReqVO) { |
| | | // 1. 校验托盘存在 |
| | | MesProPalletDO pallet = palletService.validatePalletExists(bindReqVO.getPalletId()); |
| | | // 2. 校验袋码均绑定在当前托盘上 |
| | | List<MesProBagCodeDO> bagCodes = bagCodeMapper.selectListByIds(bindReqVO.getIds()); |
| | | // 1. 锁定托盘,避免与自动归集并发修改袋数 |
| | | MesProPalletDO pallet = palletMapper.selectByIdForUpdate(bindReqVO.getPalletId()); |
| | | if (pallet == null) { |
| | | throw exception(PRO_PALLET_NOT_EXISTS); |
| | | } |
| | | // 2. 锁定并校验袋码均绑定在当前托盘上 |
| | | List<MesProBagCodeDO> bagCodes = bagCodeMapper.selectListByIdsForUpdate(bindReqVO.getIds()); |
| | | if (bagCodes.size() != bindReqVO.getIds().size()) { |
| | | throw exception(PRO_BAG_CODE_NOT_EXISTS); |
| | | } |
| | |
| | | return bagCodeMapper.selectListByBatchId(batchId); |
| | | } |
| | | |
| | | @Override |
| | | public void markOutbound(Long id, Long salesId) { |
| | | bagCodeMapper.markOutbound(id, salesId, LocalDateTime.now()); |
| | | } |
| | | |
| | | @Override |
| | | public void clearOutbound(Long id) { |
| | | bagCodeMapper.clearOutbound(id); |
| | | } |
| | | |
| | | // ==================== 私有方法 ==================== |
| | | |
| | | /** |
| | | * 校验待绑定的袋码:存在、与托盘同批次、未绑定过托盘、状态有效(已生成/已导出印刷) |
| | | */ |
| | | private List<MesProBagCodeDO> validateBagCodesForBind(List<Long> ids, MesProPalletDO pallet) { |
| | | List<MesProBagCodeDO> bagCodes = bagCodeMapper.selectListByIds(ids); |
| | | private List<MesProBagCodeDO> validateBagCodesForBind(List<Long> ids, MesProPalletDO pallet, boolean lock) { |
| | | List<MesProBagCodeDO> bagCodes = lock ? bagCodeMapper.selectListByIdsForUpdate(ids) : bagCodeMapper.selectListByIds(ids); |
| | | if (bagCodes.size() != ids.size()) { |
| | | throw exception(PRO_BAG_CODE_NOT_EXISTS); |
| | | } |