| | |
| | | import cn.iocoder.yudao.module.mes.controller.admin.pro.batch.vo.MesProBatchPageReqVO; |
| | | import cn.iocoder.yudao.module.mes.controller.admin.pro.batch.vo.MesProBatchPreGenerateReqVO; |
| | | import cn.iocoder.yudao.module.mes.controller.admin.pro.batch.vo.MesProBatchSaveReqVO; |
| | | import cn.iocoder.yudao.module.mes.dal.dataobject.mdm.MesMdmItemDO; |
| | | import cn.iocoder.yudao.module.mes.controller.admin.pro.pallet.vo.MesProPalletBindBatchReqVO; |
| | | import cn.iocoder.yudao.module.mes.dal.dataobject.pro.batch.MesProBatchDO; |
| | | import cn.iocoder.yudao.module.mes.dal.dataobject.pro.batch.MesProBatchWorkerDO; |
| | | import cn.iocoder.yudao.module.mes.dal.dataobject.pro.line.MesProLineDO; |
| | |
| | | import cn.iocoder.yudao.module.mes.enums.md.autocode.MesMdAutoCodeRuleCodeEnum; |
| | | import cn.iocoder.yudao.module.mes.enums.pro.MesProBatchStatusEnum; |
| | | import cn.iocoder.yudao.module.mes.service.md.autocode.MesMdAutoCodeRecordService; |
| | | import cn.iocoder.yudao.module.mes.service.mdm.MesMdmItemService; |
| | | import cn.iocoder.yudao.module.mes.service.pro.line.MesProLineService; |
| | | import cn.iocoder.yudao.module.mes.service.pro.pallet.MesProPalletService; |
| | | import cn.iocoder.yudao.module.mes.service.trace.integrity.MesTraceIntegrityService; |
| | | import cn.iocoder.yudao.module.system.api.user.AdminUserApi; |
| | | import jakarta.annotation.Resource; |
| | |
| | | private MesProPalletMapper palletMapper; |
| | | |
| | | @Resource |
| | | private MesProPalletService palletService; |
| | | |
| | | @Resource |
| | | private MesMdAutoCodeRecordService autoCodeRecordService; |
| | | @Resource |
| | | private AdminUserApi adminUserApi; |
| | | @Resource |
| | | private MesMdmItemService mdmItemService; |
| | | @Resource |
| | | private MesProLineService lineService; |
| | | @Resource |
| | |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public Long createBatch(MesProBatchSaveReqVO createReqVO) { |
| | | // 1. 校验关联数据(品种、产线、生产人员) |
| | | MesMdmItemDO item = mdmItemService.validateItemExists(createReqVO.getItemId()); |
| | | // 1. 校验关联数据(产线、生产人员) |
| | | MesProLineDO line = lineService.validateLineExistsAndEnable(createReqVO.getLineId()); |
| | | validateRelations(createReqVO); |
| | | |
| | | // 2. 生成批次号(编码规则:前缀 + 日期 + 产线编码 + 品种编码 + 流水号) |
| | | String code = generateBatchCode(line.getCode(), item.getCode()); |
| | | // 2. 生成批次号(编码规则:前缀 + 日期 + 产线编码 + 流水号) |
| | | String code = generateBatchCode(line.getCode()); |
| | | |
| | | // 3. 插入批次(产线编码/名称冗余回填) |
| | | // 3. 插入批次(产线编码/名称冗余回填;勾选绑定托盘时批次直接进入生产中) |
| | | boolean bindPallets = CollUtil.isNotEmpty(createReqVO.getPalletIds()); |
| | | MesProBatchDO batch = BeanUtils.toBean(createReqVO, MesProBatchDO.class) |
| | | .setCode(code) |
| | | .setLineCode(line.getCode()) |
| | | .setLineName(line.getName()) |
| | | .setBagQuantity(0) |
| | | .setPalletQuantity(0) |
| | | .setStatus(MesProBatchStatusEnum.DRAFT.getStatus()); |
| | | .setStatus(bindPallets ? MesProBatchStatusEnum.PRODUCING.getStatus() |
| | | : MesProBatchStatusEnum.DRAFT.getStatus()); |
| | | batchMapper.insert(batch); |
| | | |
| | | // 4. 插入生产人员配置 |
| | | insertBatchWorkers(batch.getId(), createReqVO.getWorkers()); |
| | | // 5. 生成批次完整性摘要 |
| | | // 5. 绑定托盘(级联生成正式托盘码并录入托盘下袋码,失败整体回滚) |
| | | bindPalletsToBatch(batch.getId(), createReqVO.getPalletIds()); |
| | | // 6. 生成批次完整性摘要 |
| | | integrityService.recordBatchIntegrity(batch.getId()); |
| | | return batch.getId(); |
| | | } |
| | |
| | | throw exception(PRO_BATCH_ALREADY_FILLED); |
| | | } |
| | | // 2. 校验关联数据并生成正式批次号 |
| | | MesMdmItemDO item = mdmItemService.validateItemExists(fillReqVO.getItemId()); |
| | | MesProLineDO line = lineService.validateLineExistsAndEnable(fillReqVO.getLineId()); |
| | | validateRelations(fillReqVO); |
| | | String code = generateBatchCode(line.getCode(), item.getCode()); |
| | | // 3. 落库业务信息(保留临时批次码用于历史扫码追溯;产线编码/名称冗余回填) |
| | | String code = generateBatchCode(line.getCode()); |
| | | // 3. 落库业务信息(保留临时批次码用于历史扫码追溯;产线编码/名称冗余回填;勾选绑定托盘时批次直接进入生产中) |
| | | boolean bindPallets = CollUtil.isNotEmpty(fillReqVO.getPalletIds()); |
| | | MesProBatchDO updateObj = BeanUtils.toBean(fillReqVO, MesProBatchDO.class) |
| | | .setCode(code) |
| | | .setLineCode(line.getCode()) |
| | | .setLineName(line.getName()) |
| | | .setStatus(MesProBatchStatusEnum.DRAFT.getStatus()); |
| | | .setStatus(bindPallets ? MesProBatchStatusEnum.PRODUCING.getStatus() |
| | | : MesProBatchStatusEnum.DRAFT.getStatus()); |
| | | batchMapper.updateById(updateObj); |
| | | // 4. 重建生产人员配置 |
| | | batchWorkerMapper.deleteByBatchId(fillReqVO.getId()); |
| | | insertBatchWorkers(fillReqVO.getId(), fillReqVO.getWorkers()); |
| | | // 5. 生成批次完整性摘要(补录正式信息后覆盖) |
| | | // 5. 绑定托盘(级联生成正式托盘码并录入托盘下袋码,失败整体回滚) |
| | | bindPalletsToBatch(fillReqVO.getId(), fillReqVO.getPalletIds()); |
| | | // 6. 生成批次完整性摘要(补录正式信息后覆盖) |
| | | integrityService.recordBatchIntegrity(fillReqVO.getId()); |
| | | } |
| | | |
| | |
| | | // 2. 校验关联数据(生产人员) |
| | | validateRelations(updateReqVO); |
| | | |
| | | // 3. 未生成正式批次号或品种/产线变化时重新生成批次号(批次号包含产线编码 + 品种编码要素) |
| | | // 3. 未生成正式批次号或产线变化时重新生成批次号(批次号包含产线编码要素) |
| | | boolean codeEmpty = StrUtil.isEmpty(oldBatch.getCode()); |
| | | boolean itemChanged = !Objects.equals(oldBatch.getItemId(), updateReqVO.getItemId()); |
| | | boolean lineChanged = !Objects.equals(oldBatch.getLineId(), updateReqVO.getLineId()); |
| | | String code = oldBatch.getCode(); |
| | | MesProBatchDO updateObj = BeanUtils.toBean(updateReqVO, MesProBatchDO.class); |
| | | if (codeEmpty || itemChanged || lineChanged) { |
| | | MesMdmItemDO item = mdmItemService.validateItemExists(updateReqVO.getItemId()); |
| | | if (codeEmpty || lineChanged) { |
| | | // 变更产线时,目标产线必须启用;未变更则仅校验存在(避免停用产线的历史批次无法编辑其他字段) |
| | | MesProLineDO line = (lineChanged || codeEmpty) |
| | | ? lineService.validateLineExistsAndEnable(updateReqVO.getLineId()) |
| | | : lineService.validateLineExists(updateReqVO.getLineId()); |
| | | code = generateBatchCode(line.getCode(), item.getCode()); |
| | | code = generateBatchCode(line.getCode()); |
| | | updateObj.setLineCode(line.getCode()).setLineName(line.getName()); |
| | | } |
| | | // 4. 更新批次 |
| | | // 4. 更新批次(勾选绑定托盘时批次直接进入生产中;取消勾选不回退,已绑定托盘不可解绑) |
| | | boolean bindPallets = CollUtil.isNotEmpty(updateReqVO.getPalletIds()); |
| | | updateObj.setCode(code); |
| | | if (bindPallets) { |
| | | updateObj.setStatus(MesProBatchStatusEnum.PRODUCING.getStatus()); |
| | | } |
| | | batchMapper.updateById(updateObj); |
| | | |
| | | // 5. 重建生产人员配置 |
| | | batchWorkerMapper.deleteByBatchId(updateReqVO.getId()); |
| | | insertBatchWorkers(updateReqVO.getId(), updateReqVO.getWorkers()); |
| | | // 6. 摘要覆盖范围含品种/产线/生产日期/计划数量,编辑后重新生成避免误报篡改 |
| | | // 6. 绑定新增勾选的托盘(级联生成正式托盘码并录入托盘下袋码,失败整体回滚) |
| | | bindPalletsToBatch(updateReqVO.getId(), updateReqVO.getPalletIds()); |
| | | // 7. 摘要覆盖范围含品种/产线/生产日期/计划数量,编辑后重新生成避免误报篡改 |
| | | integrityService.recordBatchIntegrity(updateReqVO.getId()); |
| | | } |
| | | |
| | |
| | | /** |
| | | * 校验关联数据(生产人员:责任人 + 生产人员配置) |
| | | * <p> |
| | | * 品种、产线的校验在创建/更新流程中内联执行(需取编码参与批次号生成) |
| | | * 产线的校验在创建/更新流程中内联执行(需取编码参与批次号生成) |
| | | */ |
| | | private void validateRelations(MesProBatchSaveReqVO reqVO) { |
| | | Set<Long> userIds = new HashSet<>(); |
| | |
| | | } |
| | | |
| | | /** |
| | | * 批次绑定托盘(可选):同事务内复用托盘绑定批次逻辑, |
| | | * 生成正式托盘码并级联录入托盘下未绑批次的袋码,失败整体回滚 |
| | | */ |
| | | private void bindPalletsToBatch(Long batchId, List<Long> palletIds) { |
| | | if (CollUtil.isEmpty(palletIds)) { |
| | | return; |
| | | } |
| | | MesProPalletBindBatchReqVO bindReqVO = new MesProPalletBindBatchReqVO(); |
| | | bindReqVO.setBatchId(batchId); |
| | | bindReqVO.setIds(palletIds); |
| | | palletService.bindBatch(bindReqVO); |
| | | } |
| | | |
| | | /** |
| | | * 生成批次号 |
| | | * <p> |
| | | * 编码规则:固定前缀(PC) + 日期(yyyyMMdd) + 输入字符(产线编码 + 品种编码) + 流水号(按日循环) |
| | | * 编码规则:固定前缀(PC) + 日期(yyyyMMdd) + 输入字符(产线编码) + 流水号(按日循环) |
| | | * |
| | | * @param lineCode 产线编码 |
| | | * @param itemCode 品种(物料)编码 |
| | | * @return 批次号 |
| | | */ |
| | | private String generateBatchCode(String lineCode, String itemCode) { |
| | | String inputChar = StrUtil.emptyToDefault(lineCode, "") + StrUtil.emptyToDefault(itemCode, ""); |
| | | private String generateBatchCode(String lineCode) { |
| | | String inputChar = StrUtil.emptyToDefault(lineCode, ""); |
| | | return autoCodeRecordService.generateAutoCode(MesMdAutoCodeRuleCodeEnum.PRO_BATCH_CODE.getCode(), inputChar); |
| | | } |
| | | |