yeg
2026-09-08 bafa8c8874f3dc0a1b6413b509e521872c93f57e
补齐化成工步版本标记与更新来源校验
1个文件已添加
1个文件已修改
45 ■■■■■ 已修改文件
battery-business/src/main/java/com/battery/business/report/FormationReportService.java 23 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
battery-device-bts/src/test/java/com/battery/device/bts/BtsStepDirectionResolverTest.java 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
battery-business/src/main/java/com/battery/business/report/FormationReportService.java
@@ -114,6 +114,7 @@
        settings = stepSettings(settings, matrix.items(), false);
        validateValues(settings, matrix.items()); validateChargeSelections(settings, matrix.items());
        var snapshot = new LinkedHashMap<String, Object>();
        snapshot.put("curveMode", "actual-steps");
        snapshot.put("name", request.name().trim()); snapshot.put("description", request.description());
        snapshot.put("items", matrix.items()); snapshot.put("cycleNos", matrix.cycleNos()); snapshot.put("settings", settings);
        snapshot.put("units", Map.of("chargeCapacity", "Ah", "dischargeCapacity", "Ah", "chargeEnergy", "Wh", "dischargeEnergy", "Wh", "efficiency", "%", "energyEfficiency", "%"));
@@ -157,8 +158,12 @@
        Set<String> allowed = valueKeys(settings.fields(), matrix.items());
        Map<String, String> values = new LinkedHashMap<>();
        settings.values().forEach((key, value) -> { if (allowed.contains(key)) values.put(key, value); });
        snapshot.put("items", matrix.items()); snapshot.put("cycleNos", matrix.cycleNos()); snapshot.put("settings", new Settings(settings.fields(), values,
                settings.chargeStepSelections() == null ? Map.of() : settings.chargeStepSelections(), settings.metrics(), settings.seriesColors(), settings.manualChargeSteps(), settings.curveStepSelections(), settings.hiddenSeriesKeys(), settings.activeCycle()));
        var refreshedSettings = new Settings(settings.fields(), values,
                settings.chargeStepSelections() == null ? Map.of() : settings.chargeStepSelections(), settings.metrics(), settings.seriesColors(),
                settings.manualChargeSteps(), settings.curveStepSelections(), settings.hiddenSeriesKeys(), settings.activeCycle());
        snapshot.put("curveMode", "actual-steps");
        snapshot.put("items", matrix.items()); snapshot.put("cycleNos", matrix.cycleNos());
        snapshot.put("settings", stepSettings(refreshedSettings, matrix.items(), true));
        curveUnits(snapshot);
        reports.append(id, request.baseVersionNo() + 1, snapshot.getString("name"), json(snapshot), userId, userName, "按最新来源生成:" + request.changeSummary().trim());
        return get(id, null);
@@ -297,7 +302,8 @@
            if (refresh) choice = new FormationReportRequest.StepSelection(choice.charge().stream().filter(chargeAllowed::contains).toList(), choice.discharge().stream().filter(dischargeAllowed::contains).toList());
            if (choice.charge() == null || choice.discharge() == null || !chargeAllowed.containsAll(choice.charge()) || !dischargeAllowed.containsAll(choice.discharge())
                    || new HashSet<>(choice.charge()).size() != choice.charge().size() || new HashSet<>(choice.discharge()).size() != choice.discharge().size()) throw new ServiceException("曲线工步不属于当前测试电池、循环或充放电分组");
            if (choice.charge().stream().anyMatch(choice.discharge()::contains)) throw new ServiceException("同一实际工步不能同时指定为充电和放电");
            if (choice.charge().stream().anyMatch(choice.discharge()::contains) || requested.stream().anyMatch(choice.discharge()::contains))
                throw new ServiceException("同一实际工步不能同时指定为充电和放电");
            selected.put(key, choice);
        }
        if (!refresh && ((settings.manualChargeSteps() != null && !allowed.containsAll(settings.manualChargeSteps().keySet()))
@@ -323,13 +329,9 @@
            // 早期版本未冻结工步时保持缺失,普通编辑不能重新读取设备事实。
            List<ChargeStep> choices = item.chargeSteps() == null ? List.of() : item.chargeSteps().getOrDefault(cycle, List.of());
            Integer selected = selections.get(key);
            if (choices.stream().filter(step -> isReliableCharge(step.stepType())).count() == 1) {
                int expected = choices.stream().filter(step -> isReliableCharge(step.stepType())).findFirst().get().stepNo();
                if (selected != null && selected != expected) throw new ServiceException("充电工步选择与实际工步不一致");
            } else if (!choices.isEmpty()) {
                if (selected == null) throw new ServiceException("请为无法自动识别的充电工步完成选择");
                if (choices.stream().noneMatch(step -> step.stepNo() == selected)) throw new ServiceException("所选充电工步不属于当前测试、电池和循环");
            }
            // 旧版保留冻结的单选事实,不用新增协议识别规则改判历史选择。
            if (selected != null && choices.stream().noneMatch(step -> step.stepNo() == selected))
                throw new ServiceException("所选充电工步不属于当前测试、电池和循环");
        }
    }
@@ -351,7 +353,6 @@
        }
        return result;
    }
    private boolean isReliableCharge(String type) { return directions.resolve(type) == Direction.CHARGE; }
    private int number(Object value) { return value instanceof Number n ? n.intValue() : 0; }
    private BigDecimal decimal(Object value) { return value instanceof Number n ? new BigDecimal(n.toString()) : null; }
battery-device-bts/src/test/java/com/battery/device/bts/BtsStepDirectionResolverTest.java
New file
@@ -0,0 +1,22 @@
package com.battery.device.bts;
import static org.junit.jupiter.api.Assertions.assertEquals;
import java.util.List;
import com.battery.device.api.StepDirectionResolver.Direction;
import org.junit.jupiter.api.Test;
class BtsStepDirectionResolverTest
{
    @Test
    void identifiesOnlyProtocolDirectionsAndKeepsAmbiguousTypesUnknown()
    {
        var resolver = new BtsStepDirectionResolver();
        for (String type : List.of("cc", "cv", "cccv", "cp", "cr", " CHARGE "))
            assertEquals(Direction.CHARGE, resolver.resolve(type));
        for (String type : List.of("dc", "dp", "dr", "dv", "cccd", "DISCHARGE"))
            assertEquals(Direction.DISCHARGE, resolver.resolve(type));
        for (String type : List.of("pcccv", "pulse", "sim", "rest", "恒流充电", "0.1C", ""))
            assertEquals(Direction.UNKNOWN, resolver.resolve(type));
        assertEquals(Direction.UNKNOWN, resolver.resolve(null));
    }
}