| | |
| | | import cn.iocoder.yudao.framework.common.util.collection.MapUtils; |
| | | import cn.iocoder.yudao.framework.common.util.object.BeanUtils; |
| | | import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; |
| | | import cn.iocoder.yudao.module.mes.controller.admin.pro.workorder.vo.MesProWorkOrderPageReqVO; |
| | | import cn.iocoder.yudao.module.mes.controller.admin.pro.workorder.vo.MesProWorkOrderRespVO; |
| | | import cn.iocoder.yudao.module.mes.controller.admin.pro.workorder.vo.MesProWorkOrderSaveReqVO; |
| | | import cn.iocoder.yudao.module.mes.dal.dataobject.md.client.MesMdClientDO; |
| | | import cn.iocoder.yudao.module.crm.api.customer.CrmCustomerApi; |
| | | import cn.iocoder.yudao.module.crm.api.customer.dto.CrmCustomerRespDTO; |
| | | import cn.iocoder.yudao.module.mes.controller.admin.pro.workorder.vo.*; |
| | | import cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdItemDO; |
| | | import cn.iocoder.yudao.module.mes.dal.dataobject.md.unitmeasure.MesMdUnitMeasureDO; |
| | | import cn.iocoder.yudao.module.mes.dal.dataobject.md.vendor.MesMdVendorDO; |
| | | import cn.iocoder.yudao.module.mes.dal.dataobject.pro.process.MesProProcessDO; |
| | | import cn.iocoder.yudao.module.mes.dal.dataobject.pro.task.MesProTaskDO; |
| | | import cn.iocoder.yudao.module.mes.dal.dataobject.pro.workorder.MesProWorkOrderDO; |
| | | import cn.iocoder.yudao.module.mes.service.md.client.MesMdClientService; |
| | | import cn.iocoder.yudao.module.mes.dal.dataobject.pro.workorder.MesProWorkOrderProcessDO; |
| | | import cn.iocoder.yudao.module.mes.enums.pro.MesProWorkOrderProductionStatusEnum; |
| | | import cn.iocoder.yudao.module.mes.service.md.item.MesMdItemService; |
| | | import cn.iocoder.yudao.module.mes.service.md.unitmeasure.MesMdUnitMeasureService; |
| | | import cn.iocoder.yudao.module.mes.service.md.vendor.MesMdVendorService; |
| | | import cn.iocoder.yudao.module.mes.service.pro.process.MesProProcessService; |
| | | import cn.iocoder.yudao.module.mes.service.pro.task.MesProTaskService; |
| | | import cn.iocoder.yudao.module.mes.service.pro.workorder.MesProWorkOrderProcessService; |
| | | import cn.iocoder.yudao.module.mes.service.pro.workorder.MesProWorkOrderService; |
| | | import cn.iocoder.yudao.module.srm.api.supplier.SrmSupplierApi; |
| | | import cn.iocoder.yudao.module.srm.api.supplier.dto.SrmSupplierRespDTO; |
| | | import io.swagger.v3.oas.annotations.Operation; |
| | | import io.swagger.v3.oas.annotations.Parameter; |
| | | import io.swagger.v3.oas.annotations.tags.Tag; |
| | |
| | | import org.springframework.web.bind.annotation.*; |
| | | |
| | | import java.io.IOException; |
| | | import java.math.BigDecimal; |
| | | import java.util.*; |
| | | |
| | | import static cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum.EXPORT; |
| | | import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; |
| | | import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMultiMap; |
| | | import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; |
| | | |
| | | @Tag(name = "管理后台 - MES 生产工单") |
| | |
| | | @Resource |
| | | private MesMdItemService itemService; |
| | | @Resource |
| | | private MesMdClientService clientService; |
| | | private CrmCustomerApi customerApi; |
| | | @Resource |
| | | private MesMdVendorService vendorService; |
| | | private SrmSupplierApi srmSupplierApi; |
| | | @Resource |
| | | private MesMdUnitMeasureService unitMeasureService; |
| | | @Resource |
| | | private MesProWorkOrderProcessService workOrderProcessService; |
| | | @Resource |
| | | private MesProTaskService taskService; |
| | | @Resource |
| | | private MesProProcessService processService; |
| | | |
| | | @PostMapping("/create") |
| | | @Operation(summary = "创建生产工单") |
| | |
| | | return success(new PageResult<>(buildWorkOrderRespVOList(pageResult.getList()), pageResult.getTotal())); |
| | | } |
| | | |
| | | @GetMapping("/schedule-page") |
| | | @Operation(summary = "获得生产工单调度状态分页") |
| | | @PreAuthorize("@ss.hasPermission('mes:pro-work-order:query')") |
| | | public CommonResult<PageResult<MesProWorkOrderRespVO>> getWorkOrderSchedulePage(@Valid MesProWorkOrderPageReqVO pageReqVO) { |
| | | PageResult<MesProWorkOrderDO> pageResult = workOrderService.getWorkOrderSchedulePage(pageReqVO); |
| | | return success(new PageResult<>(buildWorkOrderRespVOList(pageResult.getList()), pageResult.getTotal())); |
| | | } |
| | | |
| | | @GetMapping("/export-excel") |
| | | @Operation(summary = "导出生产工单 Excel") |
| | | @PreAuthorize("@ss.hasPermission('mes:pro-work-order:export')") |
| | |
| | | return success(true); |
| | | } |
| | | |
| | | @GetMapping("/progress/{id}") |
| | | @Operation(summary = "获取工单进度详情") |
| | | @Parameter(name = "id", description = "编号", required = true) |
| | | @PreAuthorize("@ss.hasPermission('mes:pro-work-order:query')") |
| | | public CommonResult<MesProWorkOrderProgressRespVO> getWorkOrderProgress(@PathVariable("id") Long id) { |
| | | return success(workOrderService.getWorkOrderProgress(id)); |
| | | } |
| | | |
| | | @PostMapping("/check-auto-finish/{id}") |
| | | @Operation(summary = "检查并自动完成工单") |
| | | @Parameter(name = "id", description = "编号", required = true) |
| | | @PreAuthorize("@ss.hasPermission('mes:pro-work-order:update')") |
| | | public CommonResult<Boolean> checkAutoFinish(@PathVariable("id") Long id) { |
| | | return success(workOrderService.checkAndAutoFinishWorkOrder(id)); |
| | | } |
| | | |
| | | // ==================== 拼接 VO ==================== |
| | | |
| | | private List<MesProWorkOrderRespVO> buildWorkOrderRespVOList(List<MesProWorkOrderDO> list) { |
| | |
| | | return Collections.emptyList(); |
| | | } |
| | | // 1. 批量获取关联数据 |
| | | Set<Long> workOrderIds = convertSet(list, MesProWorkOrderDO::getId); |
| | | Map<Long, MesMdItemDO> itemMap = itemService.getItemMap( |
| | | convertSet(list, MesProWorkOrderDO::getProductId)); |
| | | Map<Long, MesMdClientDO> clientMap = clientService.getClientMap( |
| | | Map<Long, CrmCustomerRespDTO> customerMap = customerApi.getCustomerMap( |
| | | convertSet(list, MesProWorkOrderDO::getClientId)); |
| | | Map<Long, MesMdVendorDO> vendorMap = vendorService.getVendorMap( |
| | | convertSet(list, MesProWorkOrderDO::getVendorId)); |
| | | Map<Long, SrmSupplierRespDTO> supplierMap = srmSupplierApi.getSupplierList( |
| | | convertSet(list, MesProWorkOrderDO::getVendorId)).getCheckedData().stream() |
| | | .collect(java.util.stream.Collectors.toMap(SrmSupplierRespDTO::getId, s -> s)); |
| | | // 单位从产品关联的 item 获得 |
| | | Map<Long, MesMdUnitMeasureDO> unitMeasureMap = unitMeasureService.getUnitMeasureMap( |
| | | convertSet(itemMap.values(), MesMdItemDO::getUnitMeasureId)); |
| | | Map<Long, MesProWorkOrderDO> parentMap = workOrderService.getWorkOrderMap( |
| | | convertSet(list, MesProWorkOrderDO::getParentId)); |
| | | |
| | | // 获取所有关联的工单工序和任务 |
| | | List<MesProWorkOrderProcessDO> allProcesses = workOrderProcessService.getWorkOrderProcessListByWorkOrderIds(workOrderIds); |
| | | List<MesProTaskDO> allTasks = taskService.getTaskListByWorkOrderIds(workOrderIds); |
| | | |
| | | Set<Long> processIds = convertSet(allProcesses, MesProWorkOrderProcessDO::getProcessId); |
| | | Map<Long, MesProProcessDO> processMap = processService.getProcessMap(processIds); |
| | | |
| | | Map<Long, List<MesProWorkOrderProcessDO>> woProcessMap = convertMultiMap(allProcesses, MesProWorkOrderProcessDO::getWorkOrderId); |
| | | Map<Long, List<MesProTaskDO>> woTaskMap = convertMultiMap(allTasks, MesProTaskDO::getWorkOrderId); |
| | | |
| | | // 2. 拼接 VO(单位名称从产品关联的 item 获得) |
| | | return BeanUtils.toBean(list, MesProWorkOrderRespVO.class, vo -> { |
| | | MapUtils.findAndThen(itemMap, vo.getProductId(), item -> { |
| | |
| | | MapUtils.findAndThen(unitMeasureMap, item.getUnitMeasureId(), |
| | | unitMeasure -> vo.setUnitMeasureName(unitMeasure.getName())); |
| | | }); |
| | | MapUtils.findAndThen(clientMap, vo.getClientId(), |
| | | client -> vo.setClientName(client.getName()).setClientCode(client.getCode())); |
| | | MapUtils.findAndThen(vendorMap, vo.getVendorId(), |
| | | vendor -> vo.setVendorName(vendor.getName()).setVendorCode(vendor.getCode())); |
| | | MapUtils.findAndThen(customerMap, vo.getClientId(), |
| | | customer -> vo.setClientName(customer.getName())); |
| | | MapUtils.findAndThen(supplierMap, vo.getVendorId(), |
| | | supplier -> vo.setVendorName(supplier.getName())); |
| | | MapUtils.findAndThen(parentMap, vo.getParentId(), |
| | | parent -> vo.setParentCode(parent.getCode())); |
| | | |
| | | // 计算完工进度 (quantityProduced / quantity * 100) |
| | | BigDecimal produced = vo.getQuantityProduced() != null ? vo.getQuantityProduced() : BigDecimal.ZERO; |
| | | if (vo.getQuantity() != null && vo.getQuantity().compareTo(BigDecimal.ZERO) > 0) { |
| | | vo.setCompletionProgress(produced.multiply(new BigDecimal("100")).divide(vo.getQuantity(), 2, java.math.RoundingMode.HALF_UP)); |
| | | } else { |
| | | vo.setCompletionProgress(produced.compareTo(BigDecimal.ZERO) > 0 ? new BigDecimal("100.00") : BigDecimal.ZERO); |
| | | } |
| | | |
| | | // 计算进度和状态 |
| | | List<MesProWorkOrderProcessDO> processes = woProcessMap.getOrDefault(vo.getId(), Collections.emptyList()); |
| | | List<MesProTaskDO> tasks = woTaskMap.getOrDefault(vo.getId(), Collections.emptyList()); |
| | | |
| | | List<MesProWorkOrderProcessProgressVO> progressList = new ArrayList<>(); |
| | | boolean allCompleted = !processes.isEmpty(); |
| | | boolean anyStarted = false; |
| | | |
| | | Map<Long, List<MesProTaskDO>> processTaskMap = convertMultiMap(tasks, MesProTaskDO::getProcessId); |
| | | |
| | | for (MesProWorkOrderProcessDO process : processes) { |
| | | List<MesProTaskDO> pTasks = processTaskMap.getOrDefault(process.getProcessId(), Collections.emptyList()); |
| | | |
| | | BigDecimal totalQty = pTasks.stream().map(t -> t.getQuantity() != null ? t.getQuantity() : BigDecimal.ZERO).reduce(BigDecimal.ZERO, BigDecimal::add); |
| | | BigDecimal totalProduced = pTasks.stream().map(t -> t.getProducedQuantity() != null ? t.getProducedQuantity() : BigDecimal.ZERO).reduce(BigDecimal.ZERO, BigDecimal::add); |
| | | |
| | | MesProWorkOrderProcessProgressVO progressVO = new MesProWorkOrderProcessProgressVO(); |
| | | MesProProcessDO processDO = processMap.get(process.getProcessId()); |
| | | progressVO.setProcessName(processDO != null ? processDO.getName() : ""); |
| | | |
| | | if (totalQty.compareTo(BigDecimal.ZERO) > 0) { |
| | | progressVO.setProgress(totalProduced.multiply(new BigDecimal("100")).divide(totalQty, 2, java.math.RoundingMode.HALF_UP)); |
| | | } else { |
| | | progressVO.setProgress(totalProduced.compareTo(BigDecimal.ZERO) > 0 ? new BigDecimal("100.00") : BigDecimal.ZERO); |
| | | } |
| | | progressList.add(progressVO); |
| | | |
| | | if (totalProduced.compareTo(BigDecimal.ZERO) > 0) { |
| | | anyStarted = true; |
| | | } |
| | | if (totalQty.compareTo(BigDecimal.ZERO) == 0 || totalProduced.compareTo(totalQty) < 0) { |
| | | allCompleted = false; |
| | | } |
| | | } |
| | | |
| | | vo.setProcessProgressList(progressList); |
| | | if (processes.isEmpty()) { |
| | | vo.setProductionStatus(MesProWorkOrderProductionStatusEnum.WAITING.getStatus()); // 待生产 |
| | | } else if (allCompleted) { |
| | | vo.setProductionStatus(MesProWorkOrderProductionStatusEnum.FINISHED.getStatus()); // 生产完成 |
| | | } else if (anyStarted) { |
| | | vo.setProductionStatus(MesProWorkOrderProductionStatusEnum.PRODUCING.getStatus()); // 生产中 |
| | | } else { |
| | | vo.setProductionStatus(MesProWorkOrderProductionStatusEnum.WAITING.getStatus()); // 待生产 |
| | | } |
| | | }); |
| | | } |
| | | |