From 990384591b79897aabf3f1f3d6c2f75005e25273 Mon Sep 17 00:00:00 2001
From: yeg <1347747024@qq.com>
Date: 星期二, 08 九月 2026 16:14:10 +0800
Subject: [PATCH] 化成报表按来源冻结详情并修正字段名称
---
battery-business/src/main/java/com/battery/business/report/FormationReportRequest.java | 10 +++++++++-
battery-business/src/main/java/com/battery/business/report/FormationReportService.java | 48 +++++++++++++++++++++++++++++++++++++++---------
2 files changed, 48 insertions(+), 10 deletions(-)
diff --git a/battery-business/src/main/java/com/battery/business/report/FormationReportRequest.java b/battery-business/src/main/java/com/battery/business/report/FormationReportRequest.java
index 67190e8..361eb51 100644
--- a/battery-business/src/main/java/com/battery/business/report/FormationReportRequest.java
+++ b/battery-business/src/main/java/com/battery/business/report/FormationReportRequest.java
@@ -20,7 +20,8 @@
public record Settings(@NotNull @Size(min = 1, max = 100) List<@NotNull @Valid FormationField> fields,
@NotNull Map<String, @NotNull String> values,
@NotNull Map<String, @NotNull Integer> chargeStepSelections,
- List<@NotNull String> metrics, Map<String, @NotNull String> seriesColors)
+ List<@NotNull String> metrics, Map<String, @NotNull String> seriesColors,
+ Map<String, @Valid DetailOverride> sourceDetailOverrides)
{
/** 旧版缺少显隐设置时显示五类指标,不补造测量快照。 */
public List<String> metrics() { return metrics == null ? List.of("voltage", "current", "positiveVoltage", "negativeVoltage", "temperature") : metrics; }
@@ -32,6 +33,13 @@
public void rejectUnknown(String field, Object value) { throw new ServiceException("化成设置不允许提交属性:" + field); }
}
+ /** 人工详情覆盖与来源快照分开保存,空字符串是明确填写值。 */
+ public record DetailOverride(@Size(max = 500) String experimentName, Map<String, @NotNull @Size(max = 500) String> fieldValues)
+ {
+ @JsonAnySetter
+ public void rejectUnknown(String field, Object value) { throw new ServiceException("详情调整不允许提交属性:" + field); }
+ }
+
/** 编辑保持后端冻结来源范围,不接收替代来源或测量。 */
public record Edit(@Positive int baseVersionNo, @NotBlank @Size(max = 100) String name,
@Size(max = 2000) String description, @NotNull @Valid Settings settings,
diff --git a/battery-business/src/main/java/com/battery/business/report/FormationReportService.java b/battery-business/src/main/java/com/battery/business/report/FormationReportService.java
index 6e8b9de..ade8f19 100644
--- a/battery-business/src/main/java/com/battery/business/report/FormationReportService.java
+++ b/battery-business/src/main/java/com/battery/business/report/FormationReportService.java
@@ -18,6 +18,7 @@
import com.battery.business.domain.TBatteryGroupField;
import com.battery.business.domain.TTest;
import com.battery.business.domain.TTestBattery;
+import com.battery.business.domain.TTestConsoleDetail;
import com.battery.business.report.FormationReportRequest.Selection;
import com.battery.business.report.FormationReportRequest.Settings;
import com.battery.business.service.ITBatteryGroupFieldService;
@@ -40,7 +41,7 @@
FormationReportRepository reports, ITBatteryGroupFieldService definitions)
{ this.tests = tests; this.data = data; this.reports = reports; this.definitions = definitions; }
- public record Candidate(Selection selection, String name, String type, long groupId, String batteryGroup, String batteryNo) { }
+ public record Candidate(Selection selection, String name, String type, long groupId, String batteryGroup, String batteryNo, TTestConsoleDetail consoleDetail) { }
public record ChargeStep(int stepNo, String name, String stepType, BigDecimal endVoltage) { }
public record Curve(Long zeroTime, List<Map<String, Object>> records) { }
public record Item(Candidate source, List<Integer> cycleNos, List<Map<String, Object>> cycles,
@@ -105,7 +106,7 @@
{
Settings settings = new Settings(validateFields(request.settings().fields(), true), request.settings().values(),
request.settings().chargeStepSelections() == null ? Map.of() : request.settings().chargeStepSelections(),
- request.settings().metrics(), request.settings().seriesColors());
+ request.settings().metrics(), request.settings().seriesColors(), request.settings().sourceDetailOverrides());
Matrix matrix = freeze(preview(request.selections()), settings.fields());
validateValues(settings, matrix.items()); validateChargeSelections(settings, matrix.items());
var snapshot = new LinkedHashMap<String, Object>();
@@ -134,9 +135,10 @@
public Map<String, Object> edit(long id, FormationReportRequest.Edit request, long userId, String userName)
{
var snapshot = current(id, request.baseVersionNo());
- validateFields(request.settings().fields(), false);
- validateValues(request.settings(), items(snapshot)); validateChargeSelections(request.settings(), items(snapshot));
- snapshot.put("name", request.name().trim()); snapshot.put("description", request.description()); snapshot.put("settings", request.settings());
+ Settings settings = new Settings(validateFields(request.settings().fields(), false), request.settings().values(),
+ request.settings().chargeStepSelections(), request.settings().metrics(), request.settings().seriesColors(), request.settings().sourceDetailOverrides());
+ validateValues(settings, items(snapshot)); validateChargeSelections(settings, items(snapshot));
+ snapshot.put("name", request.name().trim()); snapshot.put("description", request.description()); snapshot.put("settings", settings);
reports.append(id, request.baseVersionNo() + 1, request.name().trim(), json(snapshot), userId, userName, request.changeSummary().trim());
return get(id, null);
}
@@ -151,8 +153,8 @@
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()));
+ snapshot.put("items", matrix.items()); snapshot.put("cycleNos", matrix.cycleNos()); snapshot.put("settings", new Settings(validateFields(settings.fields(), false), values,
+ settings.chargeStepSelections() == null ? Map.of() : settings.chargeStepSelections(), settings.metrics(), settings.seriesColors(), settings.sourceDetailOverrides()));
curveUnits(snapshot);
reports.append(id, request.baseVersionNo() + 1, snapshot.getString("name"), json(snapshot), userId, userName, "按最新来源生成:" + request.changeSummary().trim());
return get(id, null);
@@ -170,7 +172,13 @@
var current = resolveDefinitions ? definitions.selectBatteryGroupFieldList(new TBatteryGroupField()) : List.<TBatteryGroupField>of();
return fields.stream().map(field -> {
if (!names.add(field.scope() + "|" + field.key())) throw new ServiceException("化成字段不能重复");
- if (!"battery".equals(field.kind())) return field;
+ if (!"battery".equals(field.kind())) {
+ // 仅新生成的字段结构纠正旧误写,读取历史快照时不改名。
+ String corrected = Map.of("chargePerGram", "每克N充电量", "chargePerGramTotal", "每克F充电量",
+ "capacity1v", "1.0V容量", "capacity1vf", "1.0VF克容量", "dischargeInflection", "拐点容量",
+ "dischargeInflectionTotal", "拐点F克容量").get(field.key());
+ return corrected == null ? field : new FormationField(field.key(), field.scope(), field.kind(), corrected, field.unit(), field.fieldDefinitionId());
+ }
Long id = field.fieldDefinitionId();
if (resolveDefinitions)
{
@@ -217,6 +225,15 @@
if (settings.metrics().stream().anyMatch(value -> value == null || !Set.of("voltage", "current", "positiveVoltage", "negativeVoltage", "temperature").contains(value))
|| new HashSet<>(settings.metrics()).size() != settings.metrics().size()) throw new ServiceException("化成曲线指标无效或重复");
Set<String> sources = new HashSet<>(items.stream().map(item -> item.source().selection().testId() + "|" + item.source().selection().testBatteryId()).toList());
+ if (settings.sourceDetailOverrides() != null) {
+ if (!sources.containsAll(settings.sourceDetailOverrides().keySet())) throw new ServiceException("详情调整不属于所选测试电池");
+ for (var override : settings.sourceDetailOverrides().values()) {
+ if (override == null || (override.experimentName() != null && override.experimentName().length() > 500)) throw new ServiceException("详情调整无效");
+ if (override.fieldValues() != null && override.fieldValues().entrySet().stream().anyMatch(entry ->
+ entry.getKey() == null || !entry.getKey().matches("(?:battery|special)\\|.{1,100}")
+ || entry.getValue() == null || entry.getValue().length() > 500)) throw new ServiceException("详情字段名称或值无效");
+ }
+ }
if (!sources.containsAll(settings.seriesColors().keySet()) || settings.seriesColors().values().stream()
.anyMatch(color -> color == null || !color.matches("#[0-9a-fA-F]{6}"))) throw new ServiceException("化成曲线颜色或来源无效");
if (settings.values() == null || !valueKeys(settings.fields(), items).containsAll(settings.values().keySet())
@@ -314,7 +331,20 @@
private boolean eligible(TTest test) { return "COMPLETED".equals(test.getTestStatus()) && "化成".equals(test.getTestTypeName()); }
private Candidate candidate(TTest test, TTestBattery battery)
- { return new Candidate(new Selection(test.getTestId(), battery.getTestBatteryId()), test.getTestName(), test.getTestTypeName(), battery.getGroupId(), battery.getGroupName(), battery.getBatteryNo()); }
+ { return new Candidate(new Selection(test.getTestId(), battery.getTestBatteryId()), test.getTestName(), test.getTestTypeName(), battery.getGroupId(), battery.getGroupName(), battery.getBatteryNo(), consoleDetail(test, battery)); }
+ private TTestConsoleDetail consoleDetail(TTest test, TTestBattery battery)
+ {
+ var original = test.getConsoleDetail();
+ if (original == null) return null;
+ var result = new TTestConsoleDetail();
+ result.setExperimentName(original.getExperimentName()); result.setBatteryFields(original.getBatteryFields()); result.setSpecialFields(original.getSpecialFields());
+ // 只冻结所选电池的人工详情,同名字段不推断共享身份或业务单位。
+ Map<String, Map<String, String>> values = new LinkedHashMap<>();
+ original.getFieldValues().forEach((field, byBattery) -> {
+ if (byBattery.containsKey(battery.getBatteryNo())) values.put(field, Map.of(battery.getBatteryNo(), byBattery.get(battery.getBatteryNo())));
+ });
+ result.setFieldValues(values); return result;
+ }
private List<Map<String, Object>> batteryRows(List<Map<String, Object>> rows, TTestBattery battery)
{ return rows.stream().filter(row -> Objects.equals(battery.getBatteryNo(), row.get("batteryNo"))).toList(); }
private int cycleNo(Map<String, Object> row) { return row.get("cycleNo") instanceof Number number ? number.intValue() : 0; }
--
Gitblit v1.7.1