package cn.iocoder.yudao.module.mes.api.feedback; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.common.util.json.JsonUtils; import cn.iocoder.yudao.module.mes.api.feedback.dto.MesProFeedbackWageDetailRespDTO; import cn.iocoder.yudao.module.mes.dal.dataobject.pro.feedback.MesProFeedbackDO; import cn.iocoder.yudao.module.mes.dal.dataobject.pro.process.MesProProcessDO; import cn.iocoder.yudao.module.mes.dal.mysql.pro.feedback.MesProFeedbackMapper; import cn.iocoder.yudao.module.mes.service.pro.process.MesProProcessService; import cn.iocoder.yudao.module.mes.service.pro.wage.MesProFeedbackWageBreakdown; import jakarta.annotation.Resource; import org.springframework.stereotype.Service; import org.springframework.validation.annotation.Validated; import java.math.BigDecimal; import java.time.LocalDateTime; import java.util.*; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; /** * MES 生产报工工资 API 实现类 * * @author 超级管理员 */ @Service @Validated public class MesProFeedbackWageApiImpl implements MesProFeedbackWageApi { @Resource private MesProFeedbackMapper feedbackMapper; @Resource private MesProProcessService processService; @Override public Map getWageAmountMap(Collection feedbackUserIds, LocalDateTime beginTime, LocalDateTime endTime) { if (CollUtil.isEmpty(feedbackUserIds)) { return Collections.emptyMap(); } List list = feedbackMapper.selectWageListByUserIds(feedbackUserIds, beginTime, endTime); Map result = new LinkedHashMap<>(); for (MesProFeedbackDO feedback : list) { if (feedback.getFeedbackUserId() == null) { continue; } BigDecimal wage = feedback.getWageAmount() != null ? feedback.getWageAmount() : BigDecimal.ZERO; result.merge(feedback.getFeedbackUserId(), wage, BigDecimal::add); } return result; } @Override public List getWageDetailList(Long feedbackUserId, LocalDateTime beginTime, LocalDateTime endTime) { if (feedbackUserId == null) { return Collections.emptyList(); } List list = feedbackMapper.selectWageListByUserIds( Collections.singleton(feedbackUserId), beginTime, endTime); if (CollUtil.isEmpty(list)) { return Collections.emptyList(); } Map processMap = processService.getProcessMap( convertSet(list, MesProFeedbackDO::getProcessId)); List result = new ArrayList<>(list.size()); for (MesProFeedbackDO feedback : list) { result.add(buildWageDetail(feedback, processMap.get(feedback.getProcessId()))); } // 报工时间倒序,最近的报工排在最前 result.sort(Comparator.comparing(MesProFeedbackWageDetailRespDTO::getFeedbackTime, Comparator.nullsLast(Comparator.reverseOrder()))); return result; } private MesProFeedbackWageDetailRespDTO buildWageDetail(MesProFeedbackDO feedback, MesProProcessDO process) { MesProFeedbackWageDetailRespDTO detail = new MesProFeedbackWageDetailRespDTO(); detail.setFeedbackId(feedback.getId()); detail.setFeedbackNo(feedback.getCode()); detail.setProcessId(feedback.getProcessId()); detail.setProcessName(process != null ? process.getName() : null); detail.setFeedbackTime(feedback.getFeedbackTime()); detail.setStatus(feedback.getStatus()); detail.setBillingType(feedback.getBillingType()); detail.setWorkHours(feedback.getWorkHours()); detail.setFeedbackQuantity(feedback.getFeedbackQuantity()); detail.setQualifiedQuantity(feedback.getQualifiedQuantity()); MesProFeedbackWageBreakdown breakdown = StrUtil.isNotBlank(feedback.getWageBreakdown()) ? JsonUtils.parseObject(feedback.getWageBreakdown(), MesProFeedbackWageBreakdown.class) : null; BigDecimal mainWage; BigDecimal auxWage; if (breakdown != null) { mainWage = breakdown.getMainWage() != null ? breakdown.getMainWage() : BigDecimal.ZERO; auxWage = breakdown.getAuxWage() != null ? breakdown.getAuxWage() : (feedback.getAuxWageAmount() != null ? feedback.getAuxWageAmount() : BigDecimal.ZERO); } else { // 改造前的历史报工没有工资拆分快照:把报工工资整体视为主工资, // 保证明细中「主工资 + 辅助工资 + 字段调整 + 质量调整 = 最终工资」仍然对得上 auxWage = feedback.getAuxWageAmount() != null ? feedback.getAuxWageAmount() : BigDecimal.ZERO; mainWage = feedback.getWageAmount() != null ? feedback.getWageAmount().subtract(auxWage).max(BigDecimal.ZERO) : BigDecimal.ZERO; } detail.setMainWage(mainWage); detail.setAuxWage(auxWage); // 自定义工资字段明细 List fields = new ArrayList<>(); BigDecimal fieldWage = BigDecimal.ZERO; if (breakdown != null && CollUtil.isNotEmpty(breakdown.getFields())) { for (MesProFeedbackWageBreakdown.FieldSnapshot snapshot : breakdown.getFields()) { MesProFeedbackWageDetailRespDTO.Field field = new MesProFeedbackWageDetailRespDTO.Field(); field.setCode(snapshot.getCode()); field.setName(snapshot.getName()); field.setRole(snapshot.getRole()); field.setValue(snapshot.getValue()); field.setUnitPrice(snapshot.getUnitPrice()); field.setAmount(snapshot.getAmount() != null ? snapshot.getAmount() : BigDecimal.ZERO); fields.add(field); fieldWage = fieldWage.add(field.getAmount()); } } detail.setFields(fields); detail.setFieldWage(fieldWage); BigDecimal preQualityWage = breakdown != null && breakdown.getPreQualityWage() != null ? breakdown.getPreQualityWage() : mainWage.add(auxWage).add(fieldWage); BigDecimal finalWage = feedback.getWageAmount() != null ? feedback.getWageAmount() : (breakdown != null && breakdown.getFinalWage() != null ? breakdown.getFinalWage() : preQualityWage); detail.setPreQualityWage(preQualityWage); detail.setFinalWage(finalWage); detail.setQualityAdjustment(finalWage.subtract(preQualityWage)); return detail; } }