package com.battery.business.service.impl;
|
|
import java.util.ArrayList;
|
import java.math.BigDecimal;
|
import java.time.LocalDate;
|
import java.time.LocalDateTime;
|
import java.time.format.DateTimeFormatter;
|
import java.time.format.DateTimeParseException;
|
import java.util.Date;
|
import java.util.HashMap;
|
import java.util.HashSet;
|
import java.util.List;
|
import java.util.Map;
|
import java.util.Set;
|
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.stereotype.Service;
|
import org.springframework.transaction.annotation.Transactional;
|
import com.ruoyi.common.exception.ServiceException;
|
import com.ruoyi.common.utils.StringUtils;
|
import com.battery.business.domain.TBatteryGroup;
|
import com.battery.business.domain.TBatteryGroupBattery;
|
import com.battery.business.domain.TBatteryGroupRelationField;
|
import com.battery.business.mapper.TBatteryGroupMapper;
|
import com.battery.business.service.ITBatteryGroupService;
|
|
/** 电池组管理服务实现。 */
|
@Service
|
public class TBatteryGroupServiceImpl implements ITBatteryGroupService
|
{
|
private static final String ENABLED = "0";
|
|
@Autowired
|
private TBatteryGroupMapper batteryGroupMapper;
|
|
/** 按查询条件返回未删除的电池组列表,并附带共享字段值。 */
|
@Override
|
public List<TBatteryGroup> selectBatteryGroupList(TBatteryGroup group)
|
{
|
List<TBatteryGroup> groups = batteryGroupMapper.selectBatteryGroupList(group);
|
if (groups == null)
|
{
|
return List.of();
|
}
|
for (TBatteryGroup item : groups)
|
{
|
item.setTemplateFields(batteryGroupMapper.selectRelationFields(item.getGroupId()));
|
loadSpecFields(item);
|
}
|
return groups;
|
}
|
|
/** 返回已有电池组的创建人选项。 */
|
@Override
|
public List<Map<String, Object>> selectBatteryGroupCreatorOptions()
|
{
|
return batteryGroupMapper.selectBatteryGroupCreatorOptions();
|
}
|
|
/** 返回电池组及其电池号、模板字段和值。 */
|
@Override
|
public TBatteryGroup selectBatteryGroupById(Long groupId)
|
{
|
TBatteryGroup group = batteryGroupMapper.selectBatteryGroupById(groupId);
|
if (group == null)
|
{
|
throw new ServiceException("电池组不存在");
|
}
|
group.setBatteries(batteryGroupMapper.selectBatteries(groupId));
|
group.setTemplateFields(batteryGroupMapper.selectRelationFields(groupId));
|
loadSpecFields(group);
|
return group;
|
}
|
|
/** 新增电池组并原子写入电池号和可选模板字段值。 */
|
@Override
|
@Transactional(rollbackFor = Exception.class)
|
public int insertBatteryGroup(TBatteryGroup group)
|
{
|
if (StringUtils.isEmpty(group.getStatus()))
|
{
|
group.setStatus(ENABLED);
|
}
|
validate(group, false);
|
group.setGroupName(StringUtils.trim(group.getGroupName()));
|
group.setCreateTime(new Date());
|
int rows = batteryGroupMapper.insertBatteryGroup(group);
|
replaceRelations(group);
|
batteryGroupMapper.saveSpecFields(group);
|
return rows;
|
}
|
|
/** 更新电池组并原子替换电池号和可选模板字段值。 */
|
@Override
|
@Transactional(rollbackFor = Exception.class)
|
public int updateBatteryGroup(TBatteryGroup group)
|
{
|
if (group == null || group.getGroupId() == null)
|
{
|
throw new ServiceException("电池组ID不能为空");
|
}
|
TBatteryGroup current = batteryGroupMapper.selectBatteryGroupById(group.getGroupId());
|
if (current == null)
|
{
|
throw new ServiceException("电池组不存在");
|
}
|
if (StringUtils.isEmpty(group.getStatus()))
|
{
|
group.setStatus(current.getStatus());
|
}
|
validateStatusChange(group, current.getStatus());
|
validate(group, true);
|
group.setGroupName(StringUtils.trim(group.getGroupName()));
|
group.setUpdateTime(new Date());
|
int rows = batteryGroupMapper.updateBatteryGroup(group);
|
if (rows == 0)
|
{
|
throw new ServiceException("电池组不存在或已删除");
|
}
|
replaceRelations(group);
|
batteryGroupMapper.saveSpecFields(group);
|
return rows;
|
}
|
|
/** 启用或禁用电池组,存在进行中测试时禁止禁用。 */
|
@Override
|
@Transactional(rollbackFor = Exception.class)
|
public int updateBatteryGroupStatus(TBatteryGroup group)
|
{
|
if (group == null || group.getGroupId() == null || StringUtils.isEmpty(group.getStatus()))
|
{
|
throw new ServiceException("电池组ID和目标状态不能为空");
|
}
|
if (!ENABLED.equals(group.getStatus()) && !"1".equals(group.getStatus()))
|
{
|
throw new ServiceException("电池组状态不正确");
|
}
|
if ("1".equals(group.getStatus()) && batteryGroupMapper.countTestingByGroupId(group.getGroupId()) > 0)
|
{
|
throw new ServiceException("检测中的电池组不能禁用");
|
}
|
return batteryGroupMapper.updateBatteryGroupStatus(group);
|
}
|
|
/** 逻辑删除电池组及关系,存在进行中测试时拒绝删除。 */
|
@Override
|
@Transactional(rollbackFor = Exception.class)
|
public int deleteBatteryGroupByIds(Long[] groupIds, String updateBy)
|
{
|
if (groupIds == null || groupIds.length == 0)
|
{
|
throw new ServiceException("电池组ID不能为空");
|
}
|
int rows = 0;
|
for (Long groupId : groupIds)
|
{
|
if (groupId == null)
|
{
|
continue;
|
}
|
if (batteryGroupMapper.countTestingByGroupId(groupId) > 0)
|
{
|
throw new ServiceException("检测中的电池组不能删除");
|
}
|
rows += batteryGroupMapper.deleteBatteryGroup(groupId, updateBy);
|
batteryGroupMapper.deleteBatteries(groupId);
|
batteryGroupMapper.deleteRelationFields(groupId);
|
}
|
return rows;
|
}
|
|
private void validate(TBatteryGroup group, boolean update)
|
{
|
if (group == null)
|
{
|
throw new ServiceException("电池组信息不能为空");
|
}
|
if (update && group.getGroupId() == null)
|
{
|
throw new ServiceException("电池组ID不能为空");
|
}
|
if (StringUtils.isEmpty(StringUtils.trim(group.getGroupName())))
|
{
|
throw new ServiceException("电池组名称不能为空");
|
}
|
if (StringUtils.isEmpty(StringUtils.trim(group.getModel())))
|
{
|
throw new ServiceException("电池组型号不能为空");
|
}
|
if (!ENABLED.equals(group.getStatus()) && !"1".equals(group.getStatus()))
|
{
|
throw new ServiceException("电池组状态不正确");
|
}
|
TBatteryGroup existing = batteryGroupMapper.selectBatteryGroupByName(StringUtils.trim(group.getGroupName()));
|
if (existing != null && (group.getGroupId() == null || !group.getGroupId().equals(existing.getGroupId())))
|
{
|
throw new ServiceException("电池组名称已存在");
|
}
|
if (group.getBatteryNos() == null || group.getBatteryNos().isEmpty())
|
{
|
throw new ServiceException("电池号不能为空");
|
}
|
Set<String> uniqueNos = new HashSet<>();
|
for (String batteryNo : group.getBatteryNos())
|
{
|
String normalized = StringUtils.trim(batteryNo);
|
if (StringUtils.isEmpty(normalized) || !uniqueNos.add(normalized))
|
{
|
throw new ServiceException("电池号不能重复或为空");
|
}
|
// 电池号只要求在所属电池组内唯一;不同电池组可以复用同一业务编号。
|
TBatteryGroupBattery existingBattery = batteryGroupMapper.selectBatteryByNo(normalized, group.getGroupId());
|
if (!update && existingBattery != null)
|
{
|
throw new ServiceException("所属电池组内电池号已存在");
|
}
|
}
|
if (group.getTemplateId() == null)
|
{
|
List<TBatteryGroupRelationField> values = group.getTemplateFieldRelations();
|
if (values != null && !values.isEmpty())
|
{
|
List<Long> ids = values.stream().map(TBatteryGroupRelationField::getBatteryGroupFieldId).toList();
|
if (ids.contains(null) || new HashSet<>(ids).size() != ids.size()) throw new ServiceException("字段身份无效或重复");
|
List<TBatteryGroupRelationField> definitions = batteryGroupMapper.selectCurrentFieldDefinitions(ids);
|
if (definitions.size() != ids.size()) throw new ServiceException("字段定义不存在");
|
for (TBatteryGroupRelationField value : values)
|
{
|
if (value.getFieldValue() != null && value.getFieldValue().length() > 500) throw new ServiceException("字段值过长");
|
TBatteryGroupRelationField definition = definitions.stream().filter(item -> item.getBatteryGroupFieldId().equals(value.getBatteryGroupFieldId())).findFirst().orElseThrow();
|
validateFieldValue(definition.getFieldType(), value.getFieldValue());
|
}
|
}
|
return;
|
}
|
if (batteryGroupMapper.selectTemplate(group.getTemplateId()) == null)
|
{
|
throw new ServiceException("模板不存在");
|
}
|
List<Long> fieldIds = new ArrayList<>();
|
Map<Long, String> fieldTypes = new HashMap<>();
|
if (group.getTemplateFieldRelations() != null)
|
{
|
for (TBatteryGroupRelationField relation : group.getTemplateFieldRelations())
|
{
|
if (relation == null || relation.getBatteryGroupFieldId() == null || !fieldIds.add(relation.getBatteryGroupFieldId()))
|
{
|
throw new ServiceException("模板字段关系不正确");
|
}
|
if (relation.getFieldValue() != null && relation.getFieldValue().length() > 500)
|
{
|
throw new ServiceException("模板字段值长度不能超过500个字符");
|
}
|
}
|
}
|
List<Long> templateFieldIds = batteryGroupMapper.selectTemplateFieldIds(group.getTemplateId());
|
if (templateFieldIds == null || templateFieldIds.isEmpty())
|
{
|
throw new ServiceException("模板未配置有效字段");
|
}
|
if (fieldIds.isEmpty())
|
{
|
fieldIds.addAll(templateFieldIds);
|
}
|
if (!new HashSet<>(templateFieldIds).equals(new HashSet<>(fieldIds)))
|
{
|
throw new ServiceException("电池组字段必须与模板字段一致");
|
}
|
List<TBatteryGroupRelationField> validFields = batteryGroupMapper.selectValidTemplateFields(group.getTemplateId(), fieldIds);
|
if (validFields == null || validFields.size() != fieldIds.size())
|
{
|
throw new ServiceException("电池组字段不属于指定模板");
|
}
|
for (TBatteryGroupRelationField field : validFields)
|
{
|
fieldTypes.put(field.getBatteryGroupFieldId(), field.getFieldType());
|
}
|
if (group.getTemplateFieldRelations() != null)
|
{
|
for (TBatteryGroupRelationField relation : group.getTemplateFieldRelations())
|
{
|
relation.setFieldValue(trimToNull(relation.getFieldValue()));
|
validateFieldValue(fieldTypes.get(relation.getBatteryGroupFieldId()), relation.getFieldValue());
|
}
|
}
|
}
|
|
private void loadSpecFields(TBatteryGroup group)
|
{
|
// 现有表单的固定入口投影到当前字段,不恢复主表专用字段或测试快照。
|
if (group.getTemplateFields() == null) return;
|
for (TBatteryGroupRelationField field : group.getTemplateFields())
|
{
|
if (field.getFieldName() == null) continue;
|
switch (field.getFieldName())
|
{
|
case "Z" -> group.setZ(field.getFieldValue());
|
case "H" -> group.setH(field.getFieldValue());
|
case "F" -> group.setF(field.getFieldValue());
|
case "A" -> group.setA(field.getFieldValue());
|
case "B" -> group.setB(field.getFieldValue());
|
default -> { }
|
}
|
}
|
}
|
|
private void replaceRelations(TBatteryGroup group)
|
{
|
batteryGroupMapper.deleteBatteries(group.getGroupId());
|
batteryGroupMapper.deleteRelationFields(group.getGroupId());
|
List<TBatteryGroupBattery> batteries = new ArrayList<>();
|
for (int i = 0; i < group.getBatteryNos().size(); i++)
|
{
|
TBatteryGroupBattery item = new TBatteryGroupBattery();
|
item.setGroupId(group.getGroupId());
|
item.setBatteryNo(StringUtils.trim(group.getBatteryNos().get(i)));
|
item.setSortOrder(i);
|
item.setDelFlag("0");
|
batteries.add(item);
|
}
|
batteryGroupMapper.batchInsertBatteries(batteries);
|
if (group.getTemplateId() == null && (group.getTemplateFieldRelations() == null || group.getTemplateFieldRelations().isEmpty()))
|
{
|
return;
|
}
|
List<TBatteryGroupRelationField> relations = group.getTemplateFieldRelations();
|
if (relations == null || relations.isEmpty())
|
{
|
relations = new ArrayList<>();
|
for (Long fieldId : batteryGroupMapper.selectTemplateFieldIds(group.getTemplateId()))
|
{
|
TBatteryGroupRelationField relation = new TBatteryGroupRelationField();
|
relation.setBatteryGroupFieldId(fieldId);
|
relations.add(relation);
|
}
|
}
|
for (TBatteryGroupRelationField relation : relations)
|
{
|
relation.setGroupId(group.getGroupId());
|
relation.setTemplateId(group.getTemplateId());
|
relation.setDelFlag("0");
|
}
|
batteryGroupMapper.batchInsertRelationFields(relations);
|
}
|
|
/** 按字段定义校验业务值,空值表示该字段暂未填写。 */
|
private void validateFieldValue(String fieldType, String value)
|
{
|
if (value == null || fieldType == null) return;
|
try
|
{
|
if ("number".equals(fieldType))
|
{
|
new BigDecimal(value);
|
}
|
else if ("time".equals(fieldType))
|
{
|
try
|
{
|
LocalDate.parse(value);
|
}
|
catch (DateTimeParseException exception)
|
{
|
try
|
{
|
LocalDateTime.parse(value, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
|
}
|
catch (DateTimeParseException nested)
|
{
|
LocalDateTime.parse(value);
|
}
|
}
|
}
|
}
|
catch (NumberFormatException | DateTimeParseException exception)
|
{
|
throw new ServiceException("模板字段值格式不正确");
|
}
|
}
|
|
private void validateStatusChange(TBatteryGroup group, String currentStatus)
|
{
|
if ("1".equals(group.getStatus()) && !"1".equals(currentStatus)
|
&& batteryGroupMapper.countTestingByGroupId(group.getGroupId()) > 0)
|
{
|
throw new ServiceException("测试中的电池组不能禁用");
|
}
|
}
|
|
private String trimToNull(String value)
|
{
|
String trimmed = StringUtils.trim(value);
|
return StringUtils.isEmpty(trimmed) ? null : trimmed;
|
}
|
}
|