| | |
| | | import cn.iocoder.yudao.module.mes.dal.dataobject.wm.productsales.MesWmProductSalesDetailDO; |
| | | import cn.iocoder.yudao.module.mes.dal.dataobject.wm.productsales.MesWmProductSalesLineDO; |
| | | import cn.iocoder.yudao.module.mes.dal.mysql.wm.productsales.MesWmProductSalesDetailMapper; |
| | | import cn.iocoder.yudao.module.mes.dal.mysql.wm.materialstockbag.MesWmMaterialStockBagMapper; |
| | | import cn.iocoder.yudao.module.mes.dal.mysql.wm.productsales.MesWmProductSalesMapper; |
| | | import cn.iocoder.yudao.module.mes.enums.wm.MesWmProductSalesStatusEnum; |
| | | import org.springframework.transaction.annotation.Transactional; |
| | | import cn.iocoder.yudao.module.mes.service.mdm.MesMdmItemService; |
| | | import cn.iocoder.yudao.module.mes.service.wm.materialstock.MesWmMaterialStockService; |
| | | import cn.iocoder.yudao.module.mes.service.wm.warehouse.MesWmWarehouseAreaService; |
| | |
| | | private MesWmMaterialStockService materialStockService; |
| | | @Resource |
| | | private MesWmWarehouseAreaService warehouseAreaService; |
| | | @Resource |
| | | private MesWmMaterialStockBagMapper stockBagMapper; |
| | | @Resource |
| | | private MesWmProductSalesMapper productSalesMapper; |
| | | |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public Long createProductSalesDetail(MesWmProductSalesDetailSaveReqVO createReqVO) { |
| | | lockPickingOrder(createReqVO.getSalesId()); |
| | | if (createReqVO.getRemark() != null && createReqVO.getRemark().matches("移动端无袋码拣货 #[a-f0-9-]{36}")) { |
| | | var existing = productSalesDetailMapper.selectListBySalesId(createReqVO.getSalesId()).stream() |
| | | .filter(d -> createReqVO.getRemark().equals(d.getRemark())).findFirst().orElse(null); |
| | | if (existing != null) { |
| | | if (ObjUtil.notEqual(existing.getLineId(), createReqVO.getLineId()) |
| | | || ObjUtil.notEqual(existing.getMaterialStockId(), createReqVO.getMaterialStockId()) |
| | | || existing.getQuantity().compareTo(createReqVO.getQuantity()) != 0) |
| | | throw new IllegalArgumentException("拣货请求标识已用于其他明细"); |
| | | return existing.getId(); |
| | | } |
| | | } |
| | | // 校验数据 |
| | | validateProductSalesDetailSaveData(createReqVO); |
| | | |
| | |
| | | } |
| | | |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public void updateProductSalesDetail(MesWmProductSalesDetailSaveReqVO updateReqVO) { |
| | | // 校验存在 |
| | | MesWmProductSalesDetailDO existing = validateProductSalesDetailExists(updateReqVO.getId()); |
| | | lockPickingOrder(existing.getSalesId()); |
| | | if (existing.getShipmentId() != null) throw new IllegalArgumentException("已分配发货记录的明细不能修改"); |
| | | if (ObjUtil.notEqual(existing.getSalesId(), updateReqVO.getSalesId())) throw exception(WM_PRODUCT_SALES_DETAIL_LINE_NOT_MATCH); |
| | | if (existing.getBagCodeId() != null) throw new IllegalArgumentException("扫码袋码明细不能手工修改数量或库存,请删除后重新扫码选择"); |
| | | // 校验数据 |
| | | validateProductSalesDetailSaveData(updateReqVO); |
| | |
| | | } |
| | | |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public void deleteProductSalesDetail(Long id) { |
| | | // 校验存在 |
| | | validateProductSalesDetailExists(id); |
| | | MesWmProductSalesDetailDO detail = validateProductSalesDetailExists(id); |
| | | lockPickingOrder(detail.getSalesId()); |
| | | if (detail.getShipmentId() != null) throw new IllegalArgumentException("已分配发货记录的明细不能删除"); |
| | | // 删除 |
| | | productSalesDetailMapper.deleteById(id); |
| | | } |
| | |
| | | return detail; |
| | | } |
| | | |
| | | private void lockPickingOrder(Long salesId) { |
| | | var sales = productSalesMapper.selectByIdForUpdate(salesId); |
| | | if (sales == null) throw exception(WM_PRODUCT_SALES_NOT_EXISTS); |
| | | if (!MesWmProductSalesStatusEnum.APPROVING.getStatus().equals(sales.getStatus())) { |
| | | throw exception(WM_PRODUCT_SALES_CANNOT_PICK); |
| | | } |
| | | } |
| | | |
| | | private void validateProductSalesDetailSaveData(MesWmProductSalesDetailSaveReqVO reqVO) { |
| | | if (reqVO.getQuantity() == null || reqVO.getQuantity().signum() <= 0) throw new IllegalArgumentException("拣货数量必须大于零"); |
| | | if (reqVO.getMaterialStockId() != null && stockBagMapper.selectOneActiveByMaterialStockId(reqVO.getMaterialStockId()) != null) { |
| | | throw new IllegalArgumentException("该库存存在袋码明细,请选择实际拣出的袋码"); |
| | | } |
| | | // 校验父数据(行)存在 |
| | | MesWmProductSalesLineDO line = productSalesLineService.getProductSalesLine(reqVO.getLineId()); |
| | | if (line == null) { |
| | |
| | | if (ObjUtil.notEqual(line.getSalesId(), reqVO.getSalesId())) { |
| | | throw exception(WM_PRODUCT_SALES_DETAIL_LINE_NOT_MATCH); |
| | | } |
| | | var picked = productSalesDetailMapper.selectListByLineId(line.getId()).stream() |
| | | .filter(d -> !java.util.Objects.equals(d.getId(), reqVO.getId())) |
| | | .map(MesWmProductSalesDetailDO::getQuantity).reduce(java.math.BigDecimal.ZERO, java.math.BigDecimal::add); |
| | | if (line.getQuantity() == null || picked.add(reqVO.getQuantity()).compareTo(line.getQuantity()) > 0) |
| | | throw new IllegalArgumentException("累计拣货数量不能超过出库单行计划数量"); |
| | | // 校验物料存在 |
| | | mdmItemService.validateItemExistsAndEnable(reqVO.getItemId()); |
| | | if (ObjUtil.notEqual(line.getItemId(), reqVO.getItemId())) { |
| | | throw exception(WM_PRODUCT_SALES_DETAIL_ITEM_MISMATCH); |
| | | } |
| | | if (line.getBatchCode() != null && !line.getBatchCode().isBlank() |
| | | && !java.util.Objects.equals(line.getBatchCode(), reqVO.getBatchCode())) |
| | | throw new IllegalArgumentException("所选库存批次与出库单行批次不一致"); |
| | | // 校验库位存在 |
| | | warehouseAreaService.validateWarehouseAreaExists( |
| | | reqVO.getWarehouseId(), reqVO.getLocationId(), reqVO.getAreaId()); |