From efce3bc209161bad1cb3d898fe522ed553b4a588 Mon Sep 17 00:00:00 2001 From: matevip Date: Thu, 21 May 2026 14:43:40 +0800 Subject: [PATCH] fix(goal): pin JSON wire form for GoalStatus to lowercase --- .../java/vip/mate/goal/model/GoalStatus.java | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/mateclaw-server/src/main/java/vip/mate/goal/model/GoalStatus.java b/mateclaw-server/src/main/java/vip/mate/goal/model/GoalStatus.java index 112512c9..5d6b3d27 100644 --- a/mateclaw-server/src/main/java/vip/mate/goal/model/GoalStatus.java +++ b/mateclaw-server/src/main/java/vip/mate/goal/model/GoalStatus.java @@ -1,6 +1,8 @@ package vip.mate.goal.model; import com.baomidou.mybatisplus.annotation.EnumValue; +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonValue; /** * Persistent goal lifecycle states. @@ -35,10 +37,34 @@ public enum GoalStatus { this.value = value; } + /** + * {@link JsonValue} pins the JSON-wire form to the same lowercase string + * the DB stores via {@link EnumValue}. Without this, Jackson defaults to + * {@link #name()} (uppercase) and the frontend's + * {@code status: 'active' | 'paused' | ...} TS literal types reject + * every payload — UI bug observed during PR4 manual QA. + */ + @JsonValue public String getValue() { return value; } + /** + * Accept both lowercase wire strings ("active") and uppercase Java + * names ("ACTIVE") on the inbound path so client code that constructs + * payloads either way doesn't 400. + */ + @JsonCreator + public static GoalStatus fromJson(String raw) { + if (raw == null) return null; + for (GoalStatus s : values()) { + if (s.value.equalsIgnoreCase(raw) || s.name().equalsIgnoreCase(raw)) { + return s; + } + } + throw new IllegalArgumentException("Unknown GoalStatus: " + raw); + } + /** Terminal states do not transition; they free the conversation * uniqueness slot for a fresh active goal. */ public boolean isTerminal() {