package cn.iocoder.yudao.module.mes.service.pro.wage;
|
|
import cn.hutool.core.collection.CollUtil;
|
import cn.hutool.core.util.StrUtil;
|
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
|
import cn.iocoder.yudao.framework.common.exception.ServiceException;
|
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
|
import cn.iocoder.yudao.module.mes.controller.admin.pro.wage.vo.MesProProcessWageFieldSaveListReqVO;
|
import cn.iocoder.yudao.module.mes.controller.admin.pro.wage.vo.MesProProcessWageFieldSaveReqVO;
|
import cn.iocoder.yudao.module.mes.dal.dataobject.pro.process.MesProProcessDO;
|
import cn.iocoder.yudao.module.mes.dal.dataobject.pro.wage.MesProProcessWageFieldDO;
|
import cn.iocoder.yudao.module.mes.dal.mysql.pro.wage.MesProProcessWageFieldMapper;
|
import cn.iocoder.yudao.module.mes.service.pro.process.MesProProcessService;
|
import jakarta.annotation.Resource;
|
import org.springframework.stereotype.Service;
|
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.validation.annotation.Validated;
|
|
import java.math.BigDecimal;
|
import java.util.*;
|
|
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
|
import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.*;
|
|
/**
|
* MES 工序工资字段 Service 实现类
|
*
|
* @author 超级管理员
|
*/
|
@Service
|
@Validated
|
public class MesProProcessWageFieldServiceImpl implements MesProProcessWageFieldService {
|
|
@Resource
|
private MesProProcessWageFieldMapper fieldMapper;
|
@Resource
|
private MesProProcessService processService;
|
|
@Override
|
public List<MesProProcessWageFieldDO> getFieldList(Long processId) {
|
if (processId == null) {
|
return Collections.emptyList();
|
}
|
return fieldMapper.selectListByProcessId(processId);
|
}
|
|
@Override
|
@Transactional(rollbackFor = Exception.class)
|
public void saveFieldList(MesProProcessWageFieldSaveListReqVO reqVO) {
|
MesProProcessDO process = processService.getProcess(reqVO.getProcessId());
|
if (process == null) {
|
throw exception(PRO_FEEDBACK_PROCESS_NOT_EXISTS, reqVO.getProcessId());
|
}
|
List<MesProProcessWageFieldSaveReqVO> list = reqVO.getList() == null
|
? Collections.emptyList() : reqVO.getList();
|
validateFieldList(process, list);
|
|
// 1. 已存在的字段编号
|
List<MesProProcessWageFieldDO> existingList = fieldMapper.selectListByProcessId(process.getId());
|
Set<Long> existingIds = new HashSet<>();
|
existingList.forEach(field -> existingIds.add(field.getId()));
|
Set<Long> retainedIds = new HashSet<>();
|
|
// 2. 新增 / 修改
|
for (MesProProcessWageFieldSaveReqVO item : list) {
|
MesProProcessWageFieldDO field = BeanUtils.toBean(item, MesProProcessWageFieldDO.class);
|
field.setProcessId(process.getId());
|
field.setFieldCode(StrUtil.trim(field.getFieldCode()));
|
field.setFieldName(StrUtil.trim(field.getFieldName()));
|
field.setStatus(item.getStatus() != null ? item.getStatus() : CommonStatusEnum.ENABLE.getStatus());
|
field.setSort(item.getSort() != null ? item.getSort() : 0);
|
if (field.getId() == null) {
|
fieldMapper.insert(field);
|
retainedIds.add(field.getId());
|
} else {
|
if (!existingIds.contains(field.getId())) {
|
throw exception(PRO_PROCESS_WAGE_FIELD_NOT_EXISTS);
|
}
|
fieldMapper.updateById(field);
|
retainedIds.add(field.getId());
|
}
|
}
|
|
// 3. 删除本次未保留的字段
|
for (Long existingId : existingIds) {
|
if (!retainedIds.contains(existingId)) {
|
fieldMapper.deleteById(existingId);
|
}
|
}
|
}
|
|
private void validateFieldList(MesProProcessDO process, List<MesProProcessWageFieldSaveReqVO> list) {
|
if (CollUtil.isEmpty(list)) {
|
return;
|
}
|
Set<String> codes = new HashSet<>();
|
for (MesProProcessWageFieldSaveReqVO item : list) {
|
String code = StrUtil.trim(item.getFieldCode());
|
String name = StrUtil.trim(item.getFieldName());
|
if (!codes.add(code)) {
|
throw new ServiceException(PRO_PROCESS_WAGE_FIELD_CODE_DUPLICATE.getCode(),
|
StrUtil.format("工序[{}]下字段编码[{}]重复,请修改字段编码后重试", process.getName(), code));
|
}
|
Integer fieldType = item.getFieldType();
|
if (fieldType == null || fieldType < MesProProcessWageFieldDO.FIELD_TYPE_NUMBER
|
|| fieldType > MesProProcessWageFieldDO.FIELD_TYPE_BOOLEAN) {
|
throw new ServiceException(PRO_PROCESS_WAGE_FIELD_TYPE_INVALID.getCode(),
|
StrUtil.format("工序[{}]字段[{}]的字段类型[{}]不合法;期望 1-数值 / 2-文本 / 3-下拉 / 4-布尔,请重新选择",
|
process.getName(), name, fieldType));
|
}
|
Integer calcRole = item.getCalcRole();
|
if (calcRole == null || calcRole < MesProProcessWageFieldDO.CALC_ROLE_COEFFICIENT
|
|| calcRole > MesProProcessWageFieldDO.CALC_ROLE_RECORD_ONLY) {
|
throw new ServiceException(PRO_PROCESS_WAGE_FIELD_ROLE_INVALID.getCode(),
|
StrUtil.format("工序[{}]字段[{}]的计算角色[{}]不合法;期望 1-系数 / 2-加减金额 / 3-计价数量 / 4-仅记录,请重新选择",
|
process.getName(), name, calcRole));
|
}
|
boolean numericRole = calcRole == MesProProcessWageFieldDO.CALC_ROLE_COEFFICIENT
|
|| calcRole == MesProProcessWageFieldDO.CALC_ROLE_AMOUNT
|
|| calcRole == MesProProcessWageFieldDO.CALC_ROLE_QUANTITY_PRICE;
|
if (numericRole && !Objects.equals(fieldType, MesProProcessWageFieldDO.FIELD_TYPE_NUMBER)) {
|
throw new ServiceException(PRO_PROCESS_WAGE_FIELD_TYPE_INVALID.getCode(),
|
StrUtil.format("工序[{}]字段[{}]参与工资计算,字段类型必须为「数值」,实际为[{}];请改为数值类型后重试",
|
process.getName(), name, fieldTypeName(fieldType)));
|
}
|
if (numericRole) {
|
// 固定值允许留空:由质检在过程检验单上填写,计算时系数按 1、金额/数量按 0 处理
|
BigDecimal value = parseValue(process.getName(), name, item.getFieldValue());
|
if (calcRole == MesProProcessWageFieldDO.CALC_ROLE_COEFFICIENT
|
&& value != null && value.signum() <= 0) {
|
throw new ServiceException(PRO_PROCESS_WAGE_FIELD_VALUE_INVALID.getCode(),
|
StrUtil.format("工序[{}]字段[{}]为工资系数,期望大于 0 的数值,实际为[{}];请填写大于 0 的系数,或留空由质检填写",
|
process.getName(), name, item.getFieldValue()));
|
}
|
if (calcRole == MesProProcessWageFieldDO.CALC_ROLE_QUANTITY_PRICE
|
&& (item.getUnitPrice() == null || item.getUnitPrice().signum() < 0)) {
|
throw new ServiceException(PRO_PROCESS_WAGE_FIELD_VALUE_INVALID.getCode(),
|
StrUtil.format("工序[{}]字段[{}]为计价数量,期望配置单价且不小于 0,实际为[{}];请补充单价后重试",
|
process.getName(), name, item.getUnitPrice()));
|
}
|
}
|
}
|
}
|
|
private BigDecimal parseValue(String processName, String fieldName, String fieldValue) {
|
// 留空返回 null,由质检在过程检验单填写;非空则必须是数值
|
if (StrUtil.isBlank(fieldValue)) {
|
return null;
|
}
|
try {
|
return new BigDecimal(fieldValue.trim());
|
} catch (NumberFormatException ex) {
|
throw new ServiceException(PRO_PROCESS_WAGE_FIELD_VALUE_INVALID.getCode(),
|
StrUtil.format("工序[{}]字段[{}]参与工资计算,期望数值,实际为[{}];请改为数值后重试",
|
processName, fieldName, fieldValue));
|
}
|
}
|
|
private static String fieldTypeName(Integer fieldType) {
|
if (fieldType == null) {
|
return "未知";
|
}
|
return switch (fieldType) {
|
case MesProProcessWageFieldDO.FIELD_TYPE_NUMBER -> "数值";
|
case MesProProcessWageFieldDO.FIELD_TYPE_TEXT -> "文本";
|
case MesProProcessWageFieldDO.FIELD_TYPE_SELECT -> "下拉";
|
case MesProProcessWageFieldDO.FIELD_TYPE_BOOLEAN -> "布尔";
|
default -> "未知";
|
};
|
}
|
|
}
|