diff --git a/apps/csm-portal/backend/internal/handler/cases.go b/apps/csm-portal/backend/internal/handler/cases.go index 5d21caf063..3beb1c3cd3 100644 --- a/apps/csm-portal/backend/internal/handler/cases.go +++ b/apps/csm-portal/backend/internal/handler/cases.go @@ -184,7 +184,7 @@ func (h *CaseHandler) CreateCaseComment(w http.ResponseWriter, r *http.Request) // Work notes are internal-only and exempt from the state gate. var reqMeta struct { - Type string `json:"type"` + Type string `json:"typeKey"` } _ = json.Unmarshal(body, &reqMeta) // body is already validated JSON @@ -514,7 +514,7 @@ func (h *CaseHandler) GetCaseAttachmentContent(w http.ResponseWriter, r *http.Re } // PatchCase handles PATCH /cases/{id}. -// Accepts state, priority, watchList, or assigneeEmail and forwards to the entity service. +// Accepts stateKey, priorityKey, workStateKey, watchList, or assigneeEmail and forwards to the entity service. func (h *CaseHandler) PatchCase(w http.ResponseWriter, r *http.Request) { user := middleware.UserInfoFromContext(r.Context()) if user == nil { @@ -550,8 +550,8 @@ func (h *CaseHandler) PatchCase(w http.ResponseWriter, r *http.Request) { // Validate state transition and workState guard before forwarding to the entity service. var patch struct { - State *string `json:"state"` - WorkState *string `json:"workState"` + State *string `json:"stateKey"` + WorkState *string `json:"workStateKey"` } if err := json.Unmarshal(body, &patch); err == nil && (patch.State != nil || patch.WorkState != nil) { current, err := h.entity.GetCase(r.Context(), caseID) diff --git a/apps/csm-portal/backend/internal/handler/cases_test.go b/apps/csm-portal/backend/internal/handler/cases_test.go index a307cba131..022c1ce677 100644 --- a/apps/csm-portal/backend/internal/handler/cases_test.go +++ b/apps/csm-portal/backend/internal/handler/cases_test.go @@ -56,7 +56,7 @@ func upstreamErrors(fallback string) []upstreamErrorCase { // ----- CreateCase ----- func TestCreateCase(t *testing.T) { - const validPayload = `{"projectId":"proj-1","deploymentId":"dep-1","deployedProductId":"dp-1","subject":"Login failure","description":"Users cannot log in","priority":"high","issueType":"error"}` + const validPayload = `{"projectId":"proj-1","deploymentId":"dep-1","deployedProductId":"dp-1","subject":"Login failure","description":"Users cannot log in","priorityKey":"high","issueTypeKey":"error"}` t.Run("requires authenticated user", func(t *testing.T) { h := NewCaseHandler(&mockEntityCaseClient{}) @@ -167,7 +167,7 @@ func TestCreateCase(t *testing.T) { // ----- CreateCaseComment ----- func TestCreateCaseComment(t *testing.T) { - const validPayload = `{"type":"comment","content":"Looking into this now."}` + const validPayload = `{"typeKey":"comment","content":"Looking into this now."}` t.Run("requires authenticated user", func(t *testing.T) { h := NewCaseHandler(&mockEntityCaseClient{}) @@ -280,7 +280,7 @@ func TestCreateCaseComment(t *testing.T) { }, } h := NewCaseHandler(client) - r := withUser(httptest.NewRequest(http.MethodPost, "/cases/case-1/comments", strings.NewReader(`{"type":"work_note","content":"internal note"}`))) + r := withUser(httptest.NewRequest(http.MethodPost, "/cases/case-1/comments", strings.NewReader(`{"typeKey":"work_note","content":"internal note"}`))) r.SetPathValue("id", "case-1") w := httptest.NewRecorder() h.CreateCaseComment(w, r) @@ -406,7 +406,7 @@ func TestSearchCaseComments(t *testing.T) { searchCaseCommentsFn: func(_ context.Context, caseID string, body []byte) ([]byte, error) { capturedCaseID = caseID capturedBody = body - return []byte(`{"comments":[{"id":"c-1","caseId":"case-42","commentType":"comment","body":"First comment","createdBy":"user-1","createdAt":"2026-06-03T00:00:00Z"}],"total":1,"limit":20,"offset":0,"hasMore":false}`), nil + return []byte(`{"comments":[{"id":"c-1","caseId":"case-42","type":"comment","content":"First comment","createdBy":"user-1","createdOn":"2026-06-03T00:00:00Z"}],"total":1,"limit":20,"offset":0,"hasMore":false}`), nil }, } h := NewCaseHandler(client) @@ -576,7 +576,7 @@ func TestSearchCases(t *testing.T) { func TestPatchCase(t *testing.T) { const testCaseID = "11111111-1111-1111-1111-111111111111" - const validPayload = `{"state":"work_in_progress"}` + const validPayload = `{"stateKey":"work_in_progress"}` t.Run("requires authenticated user", func(t *testing.T) { h := NewCaseHandler(&mockEntityCaseClient{}) @@ -721,7 +721,7 @@ func TestPatchCase(t *testing.T) { }, } h := NewCaseHandler(client) - r := withUser(httptest.NewRequest(http.MethodPatch, "/cases/"+testCaseID, strings.NewReader(`{"state":"work_in_progress"}`))) + r := withUser(httptest.NewRequest(http.MethodPatch, "/cases/"+testCaseID, strings.NewReader(`{"stateKey":"work_in_progress"}`))) r.SetPathValue("id", testCaseID) w := httptest.NewRecorder() h.PatchCase(w, r) @@ -742,7 +742,7 @@ func TestPatchCase(t *testing.T) { }, } h := NewCaseHandler(client) - r := withUser(httptest.NewRequest(http.MethodPatch, "/cases/"+testCaseID, strings.NewReader(`{"workState":"ongoing"}`))) + r := withUser(httptest.NewRequest(http.MethodPatch, "/cases/"+testCaseID, strings.NewReader(`{"workStateKey":"ongoing"}`))) r.SetPathValue("id", testCaseID) w := httptest.NewRecorder() h.PatchCase(w, r) @@ -764,7 +764,7 @@ func TestPatchCase(t *testing.T) { }, } h := NewCaseHandler(client) - r := withUser(httptest.NewRequest(http.MethodPatch, "/cases/"+testCaseID, strings.NewReader(`{"workState":"paused"}`))) + r := withUser(httptest.NewRequest(http.MethodPatch, "/cases/"+testCaseID, strings.NewReader(`{"workStateKey":"paused"}`))) r.SetPathValue("id", testCaseID) w := httptest.NewRecorder() h.PatchCase(w, r) @@ -779,7 +779,7 @@ func TestPatchCase(t *testing.T) { }, } h := NewCaseHandler(client) - r := withUser(httptest.NewRequest(http.MethodPatch, "/cases/"+testCaseID, strings.NewReader(`{"priority":"high"}`))) + r := withUser(httptest.NewRequest(http.MethodPatch, "/cases/"+testCaseID, strings.NewReader(`{"priorityKey":"high"}`))) r.SetPathValue("id", testCaseID) w := httptest.NewRecorder() h.PatchCase(w, r) diff --git a/apps/csm-portal/backend/openapi.yaml b/apps/csm-portal/backend/openapi.yaml index 0ad3ce2753..018390c39e 100644 --- a/apps/csm-portal/backend/openapi.yaml +++ b/apps/csm-portal/backend/openapi.yaml @@ -1284,24 +1284,24 @@ components: UpdateCaseRequest: type: object description: | - Exactly one of `state`, `priority`, `workState`, `watchList`, or `assigneeEmail` must be provided. + Exactly one of `stateKey`, `priorityKey`, `workStateKey`, `watchList`, or `assigneeEmail` must be provided. `watchList` and `assigneeEmail` are supported only for the ServiceNow data source. oneOf: - - required: [state] - - required: [priority] - - required: [workState] + - required: [stateKey] + - required: [priorityKey] + - required: [workStateKey] - required: [watchList] - required: [assigneeEmail] properties: - state: + stateKey: type: string enum: [open, work_in_progress, waiting_on_wso2, awaiting_info, reopened, solution_proposed, closed] description: The new state to transition the case to. - priority: + priorityKey: type: string enum: [catastrophic, critical, high, medium, low] description: The new priority (severity) of the case. - workState: + workStateKey: type: string enum: [ongoing, paused] description: The new work sub-state of the case. Only applicable when the case state is work_in_progress. @@ -1386,8 +1386,8 @@ components: - deployedProductId - subject - description - - priority - - issueType + - priorityKey + - issueTypeKey properties: projectId: type: string @@ -1404,11 +1404,11 @@ components: description: type: string description: Full description of the issue - priority: + priorityKey: type: string enum: [catastrophic, critical, high, medium, low] description: Urgency level of the case - issueType: + issueTypeKey: type: string enum: [error, partial_outage, performance_degradation, question, security_or_compliance, total_outage] description: Nature of the issue @@ -2304,14 +2304,14 @@ components: CaseCommentCreatePayload: type: object required: - - type - - body + - typeKey + - content properties: - type: + typeKey: type: string enum: [work_note, comment, activity] description: work_note is restricted to internal users; activity to internal and system users - body: + content: type: string description: Comment text @@ -2325,7 +2325,7 @@ components: type: type: string enum: [work_note, comment, activity] - body: + content: type: string createdBy: type: string