| | |
| | | import cn.iocoder.yudao.module.mes.enums.wm.MesWmProductSalesStatusEnum; |
| | | import cn.iocoder.yudao.module.mes.enums.wm.MesWmQualityStatusEnum; |
| | | import cn.iocoder.yudao.module.mes.enums.wm.MesWmSalesNoticeStatusEnum; |
| | | import cn.iocoder.yudao.module.mes.enums.wm.MesWmStockReserveBizTypeEnum; |
| | | import cn.iocoder.yudao.module.mes.enums.wm.MesWmTransactionTypeEnum; |
| | | import cn.iocoder.yudao.module.mes.service.md.client.MesMdClientService; |
| | | import cn.iocoder.yudao.module.mes.service.wm.materialstock.MesWmMaterialStockService; |
| | | import cn.iocoder.yudao.module.mes.service.wm.salesnotice.MesWmSalesNoticeService; |
| | | import cn.iocoder.yudao.module.mes.service.wm.stockreserve.MesWmStockReserveService; |
| | | import cn.iocoder.yudao.module.mes.service.wm.transaction.MesWmTransactionService; |
| | | import cn.iocoder.yudao.module.mes.service.wm.transaction.dto.MesWmTransactionSaveReqDTO; |
| | | import cn.iocoder.yudao.module.erp.api.sale.ErpSaleOrderApi; |
| | | import jakarta.annotation.Resource; |
| | | import org.springframework.stereotype.Service; |
| | | import org.springframework.transaction.annotation.Transactional; |
| | |
| | | private MesWmTransactionService wmTransactionService; |
| | | @Resource |
| | | private MesWmMaterialStockService materialStockService; |
| | | @Resource |
| | | private MesWmStockReserveService stockReserveService; |
| | | |
| | | @Resource |
| | | private ErpSaleOrderApi saleOrderApi; |
| | | |
| | | @Override |
| | | public Long createProductSales(MesWmProductSalesSaveReqVO createReqVO) { |
| | |
| | | if (CollUtil.isEmpty(details)) { |
| | | throw exception(WM_PRODUCT_SALES_DETAILS_EMPTY); |
| | | } |
| | | // 校验库存充足 |
| | | // 校验库存充足并创建占用 |
| | | for (MesWmProductSalesDetailDO detail : details) { |
| | | materialStockService.validateSelectedStock( |
| | | detail.getMaterialStockId(), |
| | |
| | | detail.getWarehouseId(), |
| | | detail.getLocationId(), |
| | | detail.getAreaId(), |
| | | detail.getQuantity() |
| | | ); |
| | | // 创建库存占用 |
| | | stockReserveService.createReserve( |
| | | detail.getMaterialStockId(), |
| | | MesWmStockReserveBizTypeEnum.PRODUCT_SALES.getType(), |
| | | id, |
| | | sales.getCode(), |
| | | detail.getId(), |
| | | detail.getItemId(), |
| | | detail.getQuantity() |
| | | ); |
| | | } |
| | |
| | | throw exception(WM_PRODUCT_SALES_CANNOT_FINISH); |
| | | } |
| | | |
| | | // 2. 遍历所有明细,创建库存事务(扣减库存 + 记录流水) |
| | | // 2. 确认占用转出库(释放占用量) |
| | | stockReserveService.confirmReserveToOutbound(MesWmStockReserveBizTypeEnum.PRODUCT_SALES.getType(), id); |
| | | |
| | | // 3. 遍历所有明细,创建库存事务(扣减库存 + 记录流水) |
| | | createTransactionList(sales); |
| | | |
| | | // 3. 更新出库单状态 |
| | | // 4. 更新出库单状态 |
| | | productSalesMapper.updateById(new MesWmProductSalesDO() |
| | | .setId(id).setStatus(MesWmProductSalesStatusEnum.FINISHED.getStatus())); |
| | | |
| | | // 5. 更新关联的发货通知单出库数量和状态 |
| | | if (sales.getNoticeId() != null) { |
| | | updateSalesNoticeOutCount(sales); |
| | | } |
| | | |
| | | // 6. 回写 ERP 销售订单的出库数量和状态 |
| | | updateErpSaleOrderOutCount(sales); |
| | | } |
| | | |
| | | /** |
| | | * 更新发货通知单的出库数量和状态 |
| | | */ |
| | | private void updateSalesNoticeOutCount(MesWmProductSalesDO sales) { |
| | | // 获取出库单行 |
| | | List<MesWmProductSalesLineDO> lines = productSalesLineService.getProductSalesLineListBySalesId(sales.getId()); |
| | | if (CollUtil.isEmpty(lines)) { |
| | | return; |
| | | } |
| | | // 遍历行,按 noticeLineId 更新出库数量 |
| | | for (MesWmProductSalesLineDO line : lines) { |
| | | if (line.getNoticeLineId() != null && line.getQuantity() != null) { |
| | | salesNoticeService.updateSalesNoticeLineOutCount(line.getNoticeLineId(), line.getQuantity()); |
| | | } |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 回写 ERP 销售订单的出库数量和状态 |
| | | */ |
| | | private void updateErpSaleOrderOutCount(MesWmProductSalesDO sales) { |
| | | // 获取出库单行 |
| | | List<MesWmProductSalesLineDO> lines = productSalesLineService.getProductSalesLineListBySalesId(sales.getId()); |
| | | if (CollUtil.isEmpty(lines)) { |
| | | return; |
| | | } |
| | | // 用于存储销售订单 ID,避免重复更新 |
| | | Long saleOrderId = null; |
| | | // 遍历行,按 saleOrderItemId 更新出库数量 |
| | | for (MesWmProductSalesLineDO line : lines) { |
| | | if (line.getSaleOrderItemId() != null && line.getQuantity() != null) { |
| | | saleOrderApi.updateOrderItemOutCount(line.getSaleOrderItemId(), line.getQuantity()); |
| | | // 获取销售订单 ID(从第一个有效的明细项获取) |
| | | if (saleOrderId == null) { |
| | | cn.iocoder.yudao.module.erp.api.sale.dto.ErpSaleOrderItemRespDTO itemDTO = |
| | | saleOrderApi.getSaleOrderItem(line.getSaleOrderItemId()).getCheckedData(); |
| | | if (itemDTO != null && itemDTO.getOrderId() != null) { |
| | | saleOrderId = itemDTO.getOrderId(); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | // 更新销售订单的出库状态 |
| | | if (saleOrderId != null) { |
| | | saleOrderApi.updateOrderOutStatus(saleOrderId); |
| | | } |
| | | } |
| | | |
| | | private void createTransactionList(MesWmProductSalesDO sales) { |
| | |
| | | MesWmProductSalesStatusEnum.CANCELED.getStatus())) { |
| | | throw exception(WM_PRODUCT_SALES_CANNOT_CANCEL); |
| | | } |
| | | // 释放库存占用 |
| | | stockReserveService.releaseReserve(MesWmStockReserveBizTypeEnum.PRODUCT_SALES.getType(), id); |
| | | // 取消 |
| | | productSalesMapper.updateById(new MesWmProductSalesDO() |
| | | .setId(id).setStatus(MesWmProductSalesStatusEnum.CANCELED.getStatus())); |