| | |
| | | import com.baomidou.mybatisplus.core.toolkit.Wrappers; |
| | | import com.baomidou.mybatisplus.extension.plugins.pagination.Page; |
| | | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; |
| | | import com.alibaba.fastjson2.JSON; |
| | | import com.ruoyi.approve.bean.dto.ApprovalInstanceDto; |
| | | import com.ruoyi.approve.bean.vo.ApprovalTemplateVo; |
| | | import com.ruoyi.approve.service.ApprovalInstanceService; |
| | | import com.ruoyi.approve.service.ApprovalTemplateService; |
| | | import com.ruoyi.basic.mapper.ProductMapper; |
| | | import com.ruoyi.basic.mapper.ProductModelMapper; |
| | | import com.ruoyi.basic.pojo.Product; |
| | | import com.ruoyi.basic.pojo.ProductModel; |
| | | import com.ruoyi.common.enums.TypeEnums; |
| | | import com.ruoyi.common.enums.StockInQualifiedRecordTypeEnum; |
| | | import com.ruoyi.common.enums.StockOutQualifiedRecordTypeEnum; |
| | | import com.ruoyi.common.exception.ServiceException; |
| | |
| | | private final ProductionOrderRoutingOperationParamMapper productionOrderRoutingOperationParamMapper; |
| | | private final TechnologyRoutingOperationMapper technologyRoutingOperationMapper; |
| | | private final TechnologyOperationMapper technologyOperationMapper; |
| | | private final ApprovalTemplateService approvalTemplateService; |
| | | private final ApprovalInstanceService approvalInstanceService; |
| | | private final StockUtils stockUtils; |
| | | private final StockInRecordService stockInRecordService; |
| | | private final StockInventoryService stockInventoryService; |
| | |
| | | productionProductMain.setUserName(user == null ? dto.getUserName() : user.getNickName()); |
| | | productionProductMain.setProductionOperationTaskId(taskId); |
| | | productionProductMain.setStatus(0); |
| | | productionProductMain.setReportType(dto.getReportType() == null ? 0 : dto.getReportType()); |
| | | productionProductMain.setAuditStatus(dto.getAuditStatus() == null ? 0 : dto.getAuditStatus()); |
| | | productionProductMain.setAuditRemark(dto.getAuditRemark()); |
| | | productionProductMain.setWorkHour(dto.getWorkHour()); |
| | | productionProductMainMapper.insert(productionProductMain); |
| | | syncOperationParamInputValue(dto, routingOperation.getId(), productionProductMain.getId()); |
| | | createReportApprovalInstance(productionProductMain); |
| | | |
| | | List<ProductStructureDto> productStructureDtos = resolveInputStructures( |
| | | productionOrder.getId(), routingOperation, productModel.getId()); |
| | |
| | | if (ObjectUtils.isNull(productionOrder.getStartTime())) { |
| | | productionOrder.setStartTime(LocalDateTime.now()); |
| | | } |
| | | // 订单状态由最后一道工序的合格产出推动,避免中间工序提前完工。 |
| | | productionOrder.setStatus(ProductOrderStatusEnum.RUNNING.getCode()); |
| | | // 仅待开始状态才推进到进行中,避免非末道工序报工时覆盖已完成状态。 |
| | | if (ProductOrderStatusEnum.WAIT.getCode().equals(productionOrder.getStatus())) { |
| | | productionOrder.setStatus(ProductOrderStatusEnum.RUNNING.getCode()); |
| | | } |
| | | if (isLastOperation) { |
| | | productionOrder.setCompleteQuantity(defaultDecimal(productionOrder.getCompleteQuantity()).add(productQty)); |
| | | if (productionOrder.getQuantity() != null |
| | |
| | | productionAccount.setSchedulingUserId(user == null ? null : user.getUserId()); |
| | | productionAccount.setSchedulingUserName(user == null ? dto.getUserName() : user.getNickName()); |
| | | productionAccount.setFinishedNum(productQty); |
| | | productionAccount.setWorkHours(technologyOperation.getSalaryQuota()); |
| | | productionAccount.setWorkHours(technologyOperation != null ? technologyOperation.getSalaryQuota() : null); |
| | | productionAccount.setTechnologyOperationName(technologyOperation == null ? null : technologyOperation.getName()); |
| | | productionAccount.setSchedulingDate(LocalDateTime.now()); |
| | | productionAccountMapper.insert(productionAccount); |
| | | } |
| | | if (scrapQty.compareTo(BigDecimal.ZERO) > 0) { |
| | | stockUtils.addUnStockWithBatchNo( |
| | |
| | | qualifiedBatchNo); |
| | | } |
| | | return true; |
| | | } |
| | | |
| | | private void createReportApprovalInstance(ProductionProductMain productionProductMain) { |
| | | if (productionProductMain == null || productionProductMain.getId() == null) { |
| | | return; |
| | | } |
| | | ApprovalTemplateVo templateVo = approvalTemplateService.getEnabledTemplateByBusinessType( |
| | | TypeEnums.PRODUCTION_REPORT_APPROVAL.getCode() |
| | | ); |
| | | if (templateVo == null) { |
| | | throw new ServiceException("请先配置报工审批模板"); |
| | | } |
| | | ApprovalInstanceDto approvalInstanceDto = new ApprovalInstanceDto(); |
| | | approvalInstanceDto.setTemplateId(templateVo.getId()); |
| | | approvalInstanceDto.setTemplateName(templateVo.getTemplateName()); |
| | | approvalInstanceDto.setBusinessId(productionProductMain.getId()); |
| | | approvalInstanceDto.setBusinessType(TypeEnums.PRODUCTION_REPORT_APPROVAL.getCode()); |
| | | approvalInstanceDto.setTitle(productionProductMain.getProductNo()); |
| | | approvalInstanceDto.setApplicantId(productionProductMain.getUserId()); |
| | | approvalInstanceDto.setApplicantName(productionProductMain.getUserName()); |
| | | approvalInstanceDto.setApplyTime(LocalDateTime.now()); |
| | | approvalInstanceDto.setStatus("PENDING"); |
| | | approvalInstanceDto.setFormConfig(JSON.toJSONString(buildReportApprovalFormConfig(productionProductMain))); |
| | | approvalInstanceService.add(approvalInstanceDto); |
| | | } |
| | | |
| | | private Map<String, Object> buildReportApprovalFormConfig(ProductionProductMain productionProductMain) { |
| | | Map<String, Object> formConfig = new LinkedHashMap<>(); |
| | | formConfig.put("summaryPlaceholder", "报工审批"); |
| | | formConfig.put("approvalType", "production_report"); |
| | | |
| | | List<Map<String, Object>> fields = new ArrayList<>(); |
| | | fields.add(buildReportField("productNo", "报工单号", "text", productionProductMain.getProductNo())); |
| | | fields.add(buildReportField("userName", "报工人员", "text", productionProductMain.getUserName())); |
| | | fields.add(buildReportField("workOrderNo", "工单编号", "text", resolveWorkOrderNo(productionProductMain.getProductionOperationTaskId()))); |
| | | fields.add(buildReportField("reportType", "报工结果", "select", resolveReportTypeLabel(productionProductMain.getReportType()))); |
| | | fields.add(buildReportField("workHour", "工时", "number", productionProductMain.getWorkHour())); |
| | | fields.add(buildReportField("auditStatus", "审核状态", "select", resolveAuditStatusLabel(productionProductMain.getAuditStatus()))); |
| | | fields.add(buildReportField("auditRemark", "审核意见", "textarea", productionProductMain.getAuditRemark())); |
| | | formConfig.put("fields", fields); |
| | | |
| | | Map<String, Object> formPayload = new LinkedHashMap<>(); |
| | | formPayload.put("productNo", productionProductMain.getProductNo()); |
| | | formPayload.put("userName", productionProductMain.getUserName()); |
| | | formPayload.put("workOrderNo", resolveWorkOrderNo(productionProductMain.getProductionOperationTaskId())); |
| | | formPayload.put("reportType", resolveReportTypeLabel(productionProductMain.getReportType())); |
| | | formPayload.put("workHour", productionProductMain.getWorkHour()); |
| | | formPayload.put("auditStatus", resolveAuditStatusLabel(productionProductMain.getAuditStatus())); |
| | | formPayload.put("auditRemark", productionProductMain.getAuditRemark()); |
| | | formConfig.put("formPayload", formPayload); |
| | | return formConfig; |
| | | } |
| | | |
| | | private Map<String, Object> buildReportField(String key, String label, String type, Object defaultValue) { |
| | | Map<String, Object> field = new LinkedHashMap<>(); |
| | | field.put("key", key); |
| | | field.put("label", label); |
| | | field.put("type", type); |
| | | field.put("required", Boolean.FALSE); |
| | | field.put("defaultValue", defaultValue); |
| | | return field; |
| | | } |
| | | |
| | | private String resolveWorkOrderNo(Long productionOperationTaskId) { |
| | | if (productionOperationTaskId == null) { |
| | | return null; |
| | | } |
| | | ProductionOperationTask task = productionOperationTaskMapper.selectById(productionOperationTaskId); |
| | | if (task != null && task.getWorkOrderNo() != null) { |
| | | return task.getWorkOrderNo(); |
| | | } |
| | | if (task == null || task.getProductionOrderRoutingOperationId() == null) { |
| | | return null; |
| | | } |
| | | ProductionOrderRoutingOperation routingOperation = productionOrderRoutingOperationMapper.selectById(task.getProductionOrderRoutingOperationId()); |
| | | if (routingOperation == null || routingOperation.getProductionOrderId() == null) { |
| | | return null; |
| | | } |
| | | ProductionOrder productionOrder = productionOrderMapper.selectById(routingOperation.getProductionOrderId()); |
| | | return productionOrder == null ? null : productionOrder.getNpsNo(); |
| | | } |
| | | |
| | | private String resolveReportTypeLabel(Integer reportType) { |
| | | if (reportType == null) { |
| | | return "—"; |
| | | } |
| | | switch (reportType) { |
| | | case 0: |
| | | return "合格"; |
| | | case 1: |
| | | return "轻微返工"; |
| | | case 2: |
| | | return "严重返工"; |
| | | case 3: |
| | | return "报废"; |
| | | default: |
| | | return "—"; |
| | | } |
| | | } |
| | | |
| | | private String resolveAuditStatusLabel(Integer auditStatus) { |
| | | if (auditStatus == null) { |
| | | return "待审核"; |
| | | } |
| | | switch (auditStatus) { |
| | | case 0: |
| | | return "待审核"; |
| | | case 1: |
| | | return "审核通过"; |
| | | case 2: |
| | | return "审核不通过"; |
| | | default: |
| | | return "—"; |
| | | } |
| | | } |
| | | |
| | | private String resolveLatestStockInBatchNo(Long recordId, |
| | |
| | | return dto.getProductionOperationTaskId(); |
| | | } |
| | | |
| | | private boolean isCountingWageReport(ProductionProductMain productionProductMain) { |
| | | return productionProductMain != null |
| | | && productionProductMain.getAuditStatus() != null |
| | | && productionProductMain.getAuditStatus() == 1 |
| | | && productionProductMain.getReportType() != null |
| | | && (productionProductMain.getReportType() == 0 || productionProductMain.getReportType() == 1); |
| | | } |
| | | |
| | | private boolean isExcludedFromWage(ProductionProductMain productionProductMain) { |
| | | return productionProductMain != null |
| | | && productionProductMain.getReportType() != null |
| | | && productionProductMain.getReportType() != 0 |
| | | && productionProductMain.getReportType() != 1; |
| | | } |
| | | |
| | | @Override |
| | | public Boolean auditProductMain(ProductionProductMainDto productionProductMainDto) { |
| | | if (productionProductMainDto == null || productionProductMainDto.getId() == null) { |
| | | throw new ServiceException("参数错误"); |
| | | } |
| | | ProductionProductMain productionProductMain = productionProductMainMapper.selectById(productionProductMainDto.getId()); |
| | | if (productionProductMain == null) { |
| | | throw new ServiceException("报工不存在"); |
| | | } |
| | | Integer auditStatus = productionProductMainDto.getAuditStatus(); |
| | | if (auditStatus == null) { |
| | | throw new ServiceException("审核状态不能为空"); |
| | | } |
| | | productionProductMain.setAuditStatus(auditStatus); |
| | | productionProductMain.setAuditRemark(productionProductMainDto.getAuditRemark()); |
| | | productionProductMainMapper.updateById(productionProductMain); |
| | | productionAccountMapper.delete(new LambdaQueryWrapper<ProductionAccount>() |
| | | .eq(ProductionAccount::getProductionProductMainId, productionProductMain.getId())); |
| | | if (auditStatus == 1 && !isExcludedFromWage(productionProductMain)) { |
| | | rebuildProductionAccount(productionProductMain); |
| | | } |
| | | return true; |
| | | } |
| | | |
| | | private void rebuildProductionAccount(ProductionProductMain productionProductMain) { |
| | | if (productionProductMain == null || productionProductMain.getId() == null) { |
| | | return; |
| | | } |
| | | ProductionProductOutput output = productionProductOutputMapper.selectOne( |
| | | Wrappers.<ProductionProductOutput>lambdaQuery() |
| | | .eq(ProductionProductOutput::getProductionProductMainId, productionProductMain.getId()) |
| | | .last("limit 1")); |
| | | if (output == null) { |
| | | return; |
| | | } |
| | | ProductionOperationTask productionOperationTask = productionOperationTaskMapper.selectById(productionProductMain.getProductionOperationTaskId()); |
| | | if (productionOperationTask == null) { |
| | | return; |
| | | } |
| | | ProductionOrderRoutingOperation routingOperation = productionOrderRoutingOperationMapper.selectById(productionOperationTask.getProductionOrderRoutingOperationId()); |
| | | if (routingOperation == null) { |
| | | return; |
| | | } |
| | | ProductionOrder productionOrder = productionOrderMapper.selectById(productionOperationTask.getProductionOrderId()); |
| | | if (productionOrder == null) { |
| | | return; |
| | | } |
| | | TechnologyRoutingOperation technologyRoutingOperation = technologyRoutingOperationMapper.selectById(routingOperation.getTechnologyRoutingOperationId()); |
| | | TechnologyOperation technologyOperation = technologyRoutingOperation == null ? null |
| | | : technologyOperationMapper.selectById(technologyRoutingOperation.getTechnologyOperationId()); |
| | | SysUser user = userMapper.selectUserById(productionProductMain.getUserId()); |
| | | BigDecimal productQty = defaultDecimal(output.getQuantity()); |
| | | if (productQty.compareTo(BigDecimal.ZERO) <= 0) { |
| | | return; |
| | | } |
| | | ProductionAccount productionAccount = new ProductionAccount(); |
| | | productionAccount.setProductionProductMainId(productionProductMain.getId()); |
| | | productionAccount.setSchedulingUserId(user == null ? productionProductMain.getUserId() : user.getUserId()); |
| | | productionAccount.setSchedulingUserName(user == null ? productionProductMain.getUserName() : user.getNickName()); |
| | | productionAccount.setFinishedNum(productQty); |
| | | productionAccount.setWorkHours(technologyOperation != null ? technologyOperation.getSalaryQuota() : null); |
| | | productionAccount.setTechnologyOperationName(technologyOperation == null ? null : technologyOperation.getName()); |
| | | productionAccount.setSchedulingDate(LocalDateTime.now()); |
| | | productionAccountMapper.insert(productionAccount); |
| | | } |
| | | |
| | | @Override |
| | | public ArrayList<Long> listMain(List<Long> idList) { |
| | | // 查询主表ID集合 |