Skip to content

[Customer Portal][BE] Refactor chat endpoints to conversations, update ID validation, and enhance conversation search - #224

Merged
chanukaranaba merged 7 commits into
wso2-open-operations:customer-portal-milestone-1from
Rashmika998:customer-portal-milestone-1-chat
Feb 22, 2026
Merged

chanukaranaba merged 7 commits into
wso2-open-operations:customer-portal-milestone-1from
Rashmika998:customer-portal-milestone-1-chat

Conversation

@Rashmika998

@Rashmika998 Rashmika998 commented Feb 21, 2026 •

Copy link
Copy Markdown
Contributor

Description

This PR includes the following updates:

  1. Renamed chat endpoints and related records to use "conversation"
  2. Updated endpoint validation to use IdString id instead of string id
  3. Added conversations search method
  4. Temporarily removed cases POST endpoint
  5. Add attachment POST to a deployment.

Changes

1️⃣ Rename Chat to Conversation

  • Renamed chat-related endpoints to conversation endpoints
  • Updated related records/DTOs
  • Updated routing and service-layer logic
  • Adjusted response/request models accordingly

Reason:
Using "conversation" better reflects the domain model and improves API clarity.


2️⃣ Use IdString for Validation

  • Replaced string-based string id validation with IdString id validation
  • Updated endpoint authorization/validation logic
  • Improved consistency with authentication flow

Reason:
Using IdString ensures proper user validation and aligns with authentication best practices.


3️⃣ Add Conversation Search Method

  • Implemented cases search endpoint
  • Added filtering and validation support
  • Updated related models and service logic

Reason:
Enables structured and scalable case retrieval instead of relying on simple listing logic.


4️⃣ Remove Conversations POST (Temporary)

  • Removed cases POST endpoint for now
  • Cleaned up related routing and references

5️⃣ Add endpoint to POST attachments to a deployment

  • Add an endpoint to add attachments to a deployment.

Testing

  • Verified renamed conversation endpoints function correctly
  • Tested IdString validation logic
  • Confirmed conversation search behavior with various filters
  • Ensured removed POST endpoint no longer accessible

Impact

⚠ Chat endpoints renamed (potential breaking change)
⚠ Conversation POST endpoint temporarily removed

  • Improved authentication validation using idToken

Related PRs

Summary by CodeRabbit

  • New Features

    • Conversation search/create/update endpoints with filters, sorting, and pagination.
    • Project-level conversation statistics and conversation state filter options.
    • Conversations now include a first-message flag and standardized sort/filter options.
  • Refactor

    • Renamed "chat" to "conversation" across APIs and responses.
    • Standardized ID formats and role values for consistent API payloads and endpoints.

@coderabbitai

coderabbitai Bot commented Feb 21, 2026 •

Copy link
Copy Markdown
Contributor
📝 Walkthrough

Walkthrough

Renames chat→conversation across models and APIs, standardizes many ID fields to IdString, adds conversation search/create/update endpoints and types, exposes new AI recommendation types (Role enum, public recommendation types, isFirstMessage), and renames a recommendation util function.

Changes

Cohort / File(s) Summary
AI Chat Agent types & utils
apps/customer-portal/backend/modules/ai_chat_agent/types.bal, apps/customer-portal/backend/modules/ai_chat_agent/utils.bal
Add public Role enum (USER, ASSISTANT); make RecommendationItem/RecommendationResponse/ConversationData/RecommendationRequest public; add ConversationPayload.isFirstMessage; change Message.role from string → Role; remove old Role union and trailing json...;; rename getRecommendationsForExchange → getRecommendations and use enum role constants.
Entity enums, constants & types
apps/customer-portal/backend/modules/entity/enums.bal, apps/customer-portal/backend/modules/entity/constants.bal, apps/customer-portal/backend/modules/entity/types.bal
Add public enums (SortOrder, CaseSortField, ReferenceType, CommentType, ConversationSortField); add non-public conversation state constants ACTIVE, RESOLVED; convert many string ID fields to IdString; add conversation-centric models and search/create/update payloads/responses; remove some formerly exported enums.
Entity API functions
apps/customer-portal/backend/modules/entity/entity.bal
Rename getChatStatsForProject → getConversationStatsForProject (return type updated) and add searchConversations, createConversation, updateConversation mapped to /conversations/....
Public types module
apps/customer-portal/backend/modules/types/types.bal
Rename Case.chat → Case.conversation; add conversationStates to ProjectFilterOptions; add public Conversation, ConversationResponse, ConversationSearchPayload types.
Service & utils
apps/customer-portal/backend/service.bal, apps/customer-portal/backend/utils.bal
Switch route path params from [string id] → [entity:IdString id]; migrate chat endpoints/logic to conversation search/create/update; update payload/response types to entity module types; add mapConversationSearchResponse; expose conversationStates in project filters; rename related error constant for conversation statistics.
Small constant additions/renames
apps/customer-portal/backend/modules/entity/constants.bal, apps/customer-portal/backend/constants.bal
Add ACTIVE, RESOLVED constants (non-public); rename ERR_MSG_CHATS_STATISTICS → ERR_MSG_CONVERSATION_STATISTICS.

Sequence Diagram(s)

sequenceDiagram
  participant Client as Client
  participant API as Service (service.bal)
  participant Entity as Entity Module (entity.bal)
  participant DB as Database/Store

  Client->>API: POST /projects/[id]/conversations/search (ConversationSearchPayload)
  API->>Entity: searchConversations(idToken, payload)
  Entity->>DB: query conversations (filters, pagination, sort)
  DB-->>Entity: conversations + totalRecords
  Entity-->>API: ConversationResponse
  API->>API: mapConversationSearchResponse(entityResponse)
  API-->>Client: 200 OK (types:ConversationResponse)
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~50 minutes

Possibly related PRs

Suggested reviewers

  • cloby99
  • shayanmalinda

Poem

🐰 I hopped through types and gave them a shove,
chat became conversation — neat as a glove.
IdStrings in pockets, enums standing tall,
endpoints now listen when callers call.
A rabbit applauds this tidy backend ball! 🥕✨

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarizes the main changes: refactoring chat endpoints to conversations, updating ID validation with IdString, and enhancing conversation search functionality.
Description check ✅ Passed The description covers all major changes with clear sections: chat-to-conversation rename, IdString validation updates, conversation search implementation, temporary POST endpoint removal, and deployment attachment endpoint addition, following the template's structure.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Comment thread apps/customer-portal/backend/modules/entity/constants.bal Outdated
Comment thread apps/customer-portal/backend/modules/entity/entity.bal Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 9

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
apps/customer-portal/backend/service.bal (1)

871-907: ⚠️ Potential issue | 🟡 Minor

Missing http:Forbidden in cases/search return type and error handler

The return union at line 873 omits http:Forbidden, and the error-handling block has no http:STATUS_FORBIDDEN check. The underlying searchCases call invokes an HTTP endpoint that can propagate a 403 from the entity layer. If this occurs, it silently falls through to the http:InternalServerError handler — returning a misleading 500 to the caller. The sibling conversations/search endpoint (line 996) correctly declares and handles http:Forbidden.

🛡️ Proposed fix
-    returns http:Ok|http:BadRequest|http:Unauthorized|http:InternalServerError {
+    returns http:Ok|http:BadRequest|http:Unauthorized|http:Forbidden|http:InternalServerError {
         if getStatusCode(casesResponse) == http:STATUS_UNAUTHORIZED {
             log:printWarn(string `User: ${userInfo.userId} is not authorized to access the customer portal!`);
             return <http:Unauthorized>{
                 body: {
                     message: ERR_MSG_UNAUTHORIZED_ACCESS
                 }
             };
         }
+
+        if getStatusCode(casesResponse) == http:STATUS_FORBIDDEN {
+            log:printWarn(string `User: ${userInfo.userId} is forbidden to search cases for project: ${id}`);
+            return <http:Forbidden>{
+                body: {
+                    message: ERR_MSG_PROJECT_ACCESS_FORBIDDEN
+                }
+            };
+        }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/customer-portal/backend/service.bal` around lines 871 - 907, The
resource function post projects/[entity:IdString id]/cases/search currently
omits http:Forbidden from its return union and does not handle
http:STATUS_FORBIDDEN from the searchCases call; update the function signature
to include http:Forbidden and add a branch in the casesResponse is error block
that checks if getStatusCode(casesResponse) == http:STATUS_FORBIDDEN and returns
<http:Forbidden> with an appropriate message (mirroring the pattern used for
http:STATUS_UNAUTHORIZED), so that searchCases errors propagating a 403 are
returned correctly instead of as an InternalServerError.
🧹 Nitpick comments (5)
apps/customer-portal/backend/modules/entity/types.bal (1)

447-455: ProjectConversationStatsResponse is a closed record without json...;.

Unlike most other response types in this file (e.g., ProjectCaseStatsResponse, ProjectDeploymentStatsResponse), this record doesn't include json...;. If the upstream API ever returns additional fields, deserialization will fail. This might be intentional to enforce a strict contract, but it deviates from the pattern used elsewhere.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/customer-portal/backend/modules/entity/types.bal` around lines 447 -
455, The ProjectConversationStatsResponse record is defined as a closed record
(no json...;) which will break deserialization if upstream returns extra fields;
update the ProjectConversationStatsResponse record definition to be an open
record by adding the json...; filler (i.e., include "json...;") so it matches
the pattern used by other response types like ProjectCaseStatsResponse and
ProjectDeploymentStatsResponse and safely accepts unexpected additional fields.
apps/customer-portal/backend/modules/ai_chat_agent/types.bal (1)

100-102: isFirstMessage is a required field with no default — confirm this is intentional.

Unlike other boolean fields in this module (e.g., isComplete in SlotState defaults to false), isFirstMessage has no default. Callers must always supply it explicitly. If it's expected to be false most of the time, a boolean isFirstMessage = false; default would reduce boilerplate.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/customer-portal/backend/modules/ai_chat_agent/types.bal` around lines
100 - 102, The field isFirstMessage in the message type is currently required
with no default, forcing callers to always provide it; change it to have a
default value (e.g., boolean isFirstMessage = false) if the common case is false
to reduce caller boilerplate, or explicitly document/validate its presence if it
must remain required—update the declaration for isFirstMessage accordingly in
the message type definition (and adjust any constructors/initializers that build
these types to rely on the default where appropriate).
apps/customer-portal/backend/modules/entity/constants.bal (1)

26-33: Potential confusion: RESOLVED and CLOSED both have value 3 in different state domains.

CLOSED (case state, line 27) and RESOLVED (chat state, line 32) share the integer value 3. While this compiles fine since they are distinct named constants, it can lead to subtle bugs if someone accidentally uses the wrong constant (e.g., RESOLVED where CLOSED was intended). Consider adding a comment clarifying the domain distinction, or use a naming convention that encodes the domain (e.g., CHAT_RESOLVED, CASE_CLOSED).

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/customer-portal/backend/modules/entity/constants.bal` around lines 26 -
33, CLOSED and RESOLVED both use the integer 3 in different domains which can
cause accidental misuse; update the constants to make their domains explicit
(for example rename CLOSED -> CASE_CLOSED and RESOLVED -> CHAT_RESOLVED or at
minimum add a clear comment above each group like "// Case state values" and "//
Chat state values"), then update all references/usages to the renamed symbols
(or rely on the comment if you choose not to rename) so callers use the
domain-prefixed constants (e.g., CASE_CLOSED, CHAT_RESOLVED) to avoid ambiguity.
apps/customer-portal/backend/modules/entity/enums.bal (1)

44-48: ChatSortField naming is inconsistent with the chat→conversation rename.

Throughout this PR, terminology is being migrated from "chat" to "conversation." This enum is still named ChatSortField with CHAT_CREATED_ON/CHAT_UPDATED_ON members. Consider renaming to ConversationSortField with CONVERSATION_CREATED_ON/CONVERSATION_UPDATED_ON for consistency.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/customer-portal/backend/modules/entity/enums.bal` around lines 44 - 48,
Rename the enum ChatSortField to ConversationSortField and update its members
from CHAT_CREATED_ON/CHAT_UPDATED_ON to
CONVERSATION_CREATED_ON/CONVERSATION_UPDATED_ON while preserving their string
values ("createdOn"/"updatedOn"); then update all references/usages/imports
across the codebase (including any switch/case, type annotations, serializers,
and tests) to use ConversationSortField and the new member names so the rename
is consistent with the chat→conversation migration.
apps/customer-portal/backend/service.bal (1)

1051-1055: Inconsistent path parameter name Id (capital I)

Line 1055 uses Id while every other endpoint in this file uses lowercase id. The docstring at line 1052 perpetuates the inconsistency (# + Id - ID of the project). Since this function was touched in this PR, it's a good opportunity to align the naming.

♻️ Proposed fix
-    # + Id - ID of the project
+    # + id - ID of the project
     # + conversationId - ID of the conversation
     # + return - Chat history response or error 
-    resource function get projects/[string Id]/conversations/[string conversationId](http:RequestContext ctx)
+    resource function get projects/[string id]/conversations/[string conversationId](http:RequestContext ctx)
         returns ai_chat_agent:ChatHistoryResponse|http:InternalServerError {
         ...
-        ai_chat_agent:ChatHistoryResponse|error chatHistoryResponse =
-            ai_chat_agent:getChatHistory(Id, conversationId);
+        ai_chat_agent:ChatHistoryResponse|error chatHistoryResponse =
+            ai_chat_agent:getChatHistory(id, conversationId);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/customer-portal/backend/service.bal` around lines 1051 - 1055, The route
parameter name is inconsistent: the resource function is declared as get
projects/[string Id]/conversations/[string conversationId] and the docstring
uses `Id` (capital I) while the rest of the file uses lowercase `id`; rename the
path parameter to use lowercase `id` everywhere to match conventions—update the
resource signature to projects/[string id]/conversations/[string
conversationId], update the docstring line that mentions `Id` to `id`, and
search the function body for any references to `Id` (e.g., parameter variables
or path extraction) and change them to `id` as well to keep identifiers
consistent.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@apps/customer-portal/backend/modules/ai_chat_agent/utils.bal`:
- Around line 28-29: The Message instances for user and assistant are created
with timestamp: "" which can break downstream consumers; when constructing
Message objects (Message user and Message assistant) replace the empty string
timestamp with a proper sentinel (e.g., current UTC timestamp) or a clearly
named constant indicating unused timestamp; update the creation site that sets
timestamp for the USER and ASSISTANT messages (using userMessage and
assistantMessage) to populate a real timestamp value or a documented sentinel.

In `@apps/customer-portal/backend/modules/entity/entity.bal`:
- Around line 68-77: Rename the public function getConverstationStatsForProject
to getConversationStatsForProject and fix the doc comment ("converstaion" →
"conversation"); update the function signature and its doc block, then find and
update all internal and external callers to the new name (or add a short
compatibility wrapper named getConverstationStatsForProject that delegates to
getConversationStatsForProject if you must preserve the old API). Also ensure
any references in tests, imports, or API docs that mention
getConverstationStatsForProject are updated; the function interacts with
csEntityClient->/projects/[id]/conversations/stats.get(generateHeaders(idToken)),
so keep that call unchanged.
- Around line 336-340: The searchConversations function is calling the old
endpoint csEntityClient->/chats/search.post; update it to call
csEntityClient->/conversations/search.post so it matches the migrated entity API
and the other conversation methods (e.g., createConversation,
updateConversation, getConverstationStatsForProject); ensure you continue to
pass payload and generateHeaders(idToken) unchanged.

In `@apps/customer-portal/backend/modules/entity/types.bal`:
- Around line 362-363: Fix the typo in the documentation comment above the
ChoiceListItem[] conversationStates field: change "converstaion" to
"conversation" (also apply the same correction where the same typo appears in
entity.bal) so the comment reads "List of available conversation states" and
matches the field name conversationStates.
- Around line 1091-1112: Update the stale doc comments in the Conversation
record: change references from "chat" to "conversation" in the type header and
field comments (e.g., the top-line comment for Conversation and the comments for
id, number, initialMessage, and createdBy). Edit the comment texts adjacent to
the Conversation declaration and its fields (including IdString id, string?
number, string? initialMessage, and string createdBy) so they consistently say
"conversation" instead of "chat".

In `@apps/customer-portal/backend/modules/types/types.bal`:
- Around line 763-770: The public record type ConversationResponse uses the
field name chats but should be conversations to match the entity layer
(entity:ConversationResponse) and the chat→conversation rename; update the type
definition in ConversationResponse to rename the chats field to conversations
and then update any usages (notably the mapper function
mapConversationSearchResponse in utils.bal) to populate and read conversations
instead of chats so names are consistent across the API and entity types.
- Around line 740-761: The doc comment for the createdBy field in the
Conversation record uses "User who created the chat" which is inconsistent;
update that comment to "User who created the conversation" (locate the public
type Conversation and edit the comment above the createdBy field) so terminology
matches the rest of the type.

In `@apps/customer-portal/backend/service.bal`:
- Line 994: The resource signature for the POST endpoint currently uses an
unconstrained path parameter "[string id]"—update the resource declaration
"resource function post projects/[string id]/conversations/search(...)" to use
the refactored type "[entity:IdString id]" so the endpoint matches other
project-scoped handlers and benefits from the built-in ID validation; ensure any
references to the path parameter inside the function keep the same name "id" and
compile against the entity:IdString type.

In `@apps/customer-portal/backend/utils.bal`:
- Around line 427-456: The doc comment and variable/field names still refer to
"Chat" and "chats": update the comment in mapConversationSearchResponse to say
"Conversation search response" and "Mapped conversation search response", rename
the local variable chats to conversations (and its comprehension target from
response.conversations if needed), and change the returned property key from
chats to conversations to match the renamed
types:ConversationResponse.conversations; ensure any references to
types:ConversationResponse.chats are updated to
types:ConversationResponse.conversations and adjust the select/return
accordingly.

---

Outside diff comments:
In `@apps/customer-portal/backend/service.bal`:
- Around line 871-907: The resource function post projects/[entity:IdString
id]/cases/search currently omits http:Forbidden from its return union and does
not handle http:STATUS_FORBIDDEN from the searchCases call; update the function
signature to include http:Forbidden and add a branch in the casesResponse is
error block that checks if getStatusCode(casesResponse) == http:STATUS_FORBIDDEN
and returns <http:Forbidden> with an appropriate message (mirroring the pattern
used for http:STATUS_UNAUTHORIZED), so that searchCases errors propagating a 403
are returned correctly instead of as an InternalServerError.

---

Nitpick comments:
In `@apps/customer-portal/backend/modules/ai_chat_agent/types.bal`:
- Around line 100-102: The field isFirstMessage in the message type is currently
required with no default, forcing callers to always provide it; change it to
have a default value (e.g., boolean isFirstMessage = false) if the common case
is false to reduce caller boilerplate, or explicitly document/validate its
presence if it must remain required—update the declaration for isFirstMessage
accordingly in the message type definition (and adjust any
constructors/initializers that build these types to rely on the default where
appropriate).

In `@apps/customer-portal/backend/modules/entity/constants.bal`:
- Around line 26-33: CLOSED and RESOLVED both use the integer 3 in different
domains which can cause accidental misuse; update the constants to make their
domains explicit (for example rename CLOSED -> CASE_CLOSED and RESOLVED ->
CHAT_RESOLVED or at minimum add a clear comment above each group like "// Case
state values" and "// Chat state values"), then update all references/usages to
the renamed symbols (or rely on the comment if you choose not to rename) so
callers use the domain-prefixed constants (e.g., CASE_CLOSED, CHAT_RESOLVED) to
avoid ambiguity.

In `@apps/customer-portal/backend/modules/entity/enums.bal`:
- Around line 44-48: Rename the enum ChatSortField to ConversationSortField and
update its members from CHAT_CREATED_ON/CHAT_UPDATED_ON to
CONVERSATION_CREATED_ON/CONVERSATION_UPDATED_ON while preserving their string
values ("createdOn"/"updatedOn"); then update all references/usages/imports
across the codebase (including any switch/case, type annotations, serializers,
and tests) to use ConversationSortField and the new member names so the rename
is consistent with the chat→conversation migration.

In `@apps/customer-portal/backend/modules/entity/types.bal`:
- Around line 447-455: The ProjectConversationStatsResponse record is defined as
a closed record (no json...;) which will break deserialization if upstream
returns extra fields; update the ProjectConversationStatsResponse record
definition to be an open record by adding the json...; filler (i.e., include
"json...;") so it matches the pattern used by other response types like
ProjectCaseStatsResponse and ProjectDeploymentStatsResponse and safely accepts
unexpected additional fields.

In `@apps/customer-portal/backend/service.bal`:
- Around line 1051-1055: The route parameter name is inconsistent: the resource
function is declared as get projects/[string Id]/conversations/[string
conversationId] and the docstring uses `Id` (capital I) while the rest of the
file uses lowercase `id`; rename the path parameter to use lowercase `id`
everywhere to match conventions—update the resource signature to
projects/[string id]/conversations/[string conversationId], update the docstring
line that mentions `Id` to `id`, and search the function body for any references
to `Id` (e.g., parameter variables or path extraction) and change them to `id`
as well to keep identifiers consistent.

Comment thread apps/customer-portal/backend/modules/ai_chat_agent/utils.bal
Comment thread apps/customer-portal/backend/modules/entity/entity.bal Outdated
Comment thread apps/customer-portal/backend/modules/entity/entity.bal
Comment thread apps/customer-portal/backend/modules/entity/types.bal Outdated
Comment thread apps/customer-portal/backend/modules/entity/types.bal Outdated
Comment thread apps/customer-portal/backend/modules/types/types.bal
Comment thread apps/customer-portal/backend/modules/types/types.bal
Comment thread apps/customer-portal/backend/service.bal Outdated
Comment thread apps/customer-portal/backend/utils.bal
Comment thread apps/customer-portal/backend/modules/entity/enums.bal Outdated
Comment thread apps/customer-portal/backend/modules/types/types.bal Outdated
@Rashmika998 Rashmika998 changed the title [Customer Portal][BE] Refactor chat endpoints to conversations, update ID validation, and enhance case search [Customer Portal][BE] Refactor chat endpoints to conversations, update ID validation, and enhance conversation search Feb 21, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
apps/customer-portal/backend/service.bal (1)

1050-1078: ⚠️ Potential issue | 🟠 Major

Chat history endpoint not updated to use entity:IdString and has naming inconsistencies.

This endpoint has several issues relative to the rest of the PR:

  1. Path parameter [string Id] (line 1055) uses uppercase "I" — every other endpoint uses lowercase id. This is also inconsistent with the PR-wide migration to entity:IdString.
  2. Doc comment on line 1052 says # + Id instead of # + id.
  3. Missing Unauthorized/Forbidden error handling — other project-scoped endpoints verify project access and return 401/403, but this one only returns InternalServerError.
Proposed fix for naming and ID type consistency
     # Get chat history for a specific conversation.
-    #
-    # + Id - ID of the project
+    #
+    # + id - ID of the project
     # + conversationId - ID of the conversation
     # + return - Chat history response or error 
-    resource function get projects/[string Id]/conversations/[string conversationId](http:RequestContext ctx)
+    resource function get projects/[entity:IdString id]/conversations/[entity:IdString conversationId](http:RequestContext ctx)
         returns ai_chat_agent:ChatHistoryResponse|http:InternalServerError {
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/customer-portal/backend/service.bal` around lines 1050 - 1078, Change
the resource function signature and docs to use lowercase id of type
entity:IdString (resource function get projects/[entity:IdString
id]/conversations/[string conversationId]) and update the doc comment from "Id"
to "id"; rename all uses of Id to id (including the ai_chat_agent:getChatHistory
call). After extracting userInfo (authorization:UserInfoPayload|error userInfo =
ctx.getWithType(authorization:HEADER_USER_INFO)), call the same project-access
verification used by other project-scoped endpoints (the existing helper used
elsewhere to return 401/403) and return http:Unauthorized or http:Forbidden as
appropriate before calling ai_chat_agent:getChatHistory; keep the existing error
logging (ERR_MSG_USER_INFO_HEADER_NOT_FOUND and log:printError) and preserve the
InternalServerError path for getChatHistory failures.
apps/customer-portal/backend/modules/entity/types.bal (1)

447-455: ⚠️ Potential issue | 🟡 Minor

Stale "chat" in doc comment on line 449.

The type was renamed to ProjectConversationStatsResponse, but line 449 still says "Active chat count". Should be "Active conversation count" (and similarly "Session count" and "Resolved count" are fine).

Proposed fix
 # Project conversation statistics response.
 public type ProjectConversationStatsResponse record {|
-    # Active chat count
+    # Active conversation count
     int activeCount;
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/customer-portal/backend/modules/entity/types.bal` around lines 447 -
455, Update the stale doc comment for the ProjectConversationStatsResponse
record: change the comment on the activeCount field that currently reads "Active
chat count" to "Active conversation count" so it matches the renamed type;
locate the ProjectConversationStatsResponse type and modify the comment above
activeCount accordingly.
🧹 Nitpick comments (5)
apps/customer-portal/backend/modules/types/types.bal (2)

188-198: Stale "chats" terminology in ProjectSupportStats fields.

The fields activeChats, sessionChats, and resolvedChats still use "chats" terminology, which is inconsistent with the broader chat→conversation rename in this PR. If these field names are part of a public API contract, this is a breaking change concern either way — consider renaming them to activeConversations, sessionConversations, and resolvedConversations to stay consistent.

Proposed fix
 public type ProjectSupportStats record {|
     # Total cases count
     int totalCases?;
-    # Active chats count
-    int activeChats?;
-    # Session chats count
-    int sessionChats?;
-    # Resolved chats count
-    int resolvedChats?;
+    # Active conversations count
+    int activeConversations?;
+    # Session conversations count
+    int sessionConversations?;
+    # Resolved conversations count
+    int resolvedConversations?;
 |};

Note: This would also require updating the corresponding return values in service.bal (lines 681-689) where these fields are populated.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/customer-portal/backend/modules/types/types.bal` around lines 188 - 198,
Rename the stale "chats" fields in the ProjectSupportStats record to use
"Conversations" (change activeChats → activeConversations, sessionChats →
sessionConversations, resolvedChats → resolvedConversations) and update every
place that constructs or reads ProjectSupportStats (notably where the record is
populated in service.bal) to use the new field names; ensure any
serialization/exposed API mappings are updated to avoid mismatches and run tests
to catch any remaining references to the old field names.

200-210: Same stale "chats" terminology in ProjectStats.

ProjectStats.activeChats (line 205) should also be renamed for consistency with the chat→conversation migration.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/customer-portal/backend/modules/types/types.bal` around lines 200 - 210,
ProjectStats still uses the old field name activeChats; rename that field to
activeConversations in the ProjectStats record definition (replace activeChats?
with activeConversations?) and update every usage site that references
ProjectStats.activeChats — assignments, destructuring, JSON mapping, and tests —
to use ProjectStats.activeConversations so the type and all consumers reflect
the chat→conversation migration consistently.
apps/customer-portal/backend/service.bal (3)

409-411: patch projects/[string projectId]/deployments/[string deploymentId] not migrated to entity:IdString.

Other project and deployment endpoints (lines 267, 314, 353) use entity:IdString, but this PATCH endpoint still uses string for both path parameters. This leaves an inconsistency where these IDs skip the hex validation that other endpoints enforce.

Proposed fix
-    resource function patch projects/[string projectId]/deployments/[string deploymentId](http:RequestContext ctx,
+    resource function patch projects/[entity:IdString projectId]/deployments/[entity:IdString deploymentId](http:RequestContext ctx,
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/customer-portal/backend/service.bal` around lines 409 - 411, The PATCH
resource signature uses plain string path params which bypass hex validation;
update the resource declaration resource function patch projects/[string
projectId]/deployments/[string deploymentId](...) to use the validated type
entity:IdString for both path params (e.g., projects/[entity:IdString
projectId]/deployments/[entity:IdString deploymentId]) so it matches the other
endpoints (see resource functions at lines with entity:IdString) and adjust any
local parameter references if necessary to the same names; no other behavioral
changes are required.

1391-1393: patch deployments/[string deploymentId]/products/[string productId] not migrated to entity:IdString.

Same inconsistency — other deployment and product endpoints use entity:IdString but this one still uses string for both path parameters.

Proposed fix
-    resource function patch deployments/[string deploymentId]/products/[string productId](http:RequestContext ctx,
+    resource function patch deployments/[entity:IdString deploymentId]/products/[entity:IdString productId](http:RequestContext ctx,
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/customer-portal/backend/service.bal` around lines 1391 - 1393, The
resource function signature for patch deployments/[string
deploymentId]/products/[string productId] uses plain string path parameters;
change both path parameter types to entity:IdString to match other endpoints by
updating the resource function declaration (the symbol to edit is the resource
function named "patch deployments/[string deploymentId]/products/[string
productId]") so it reads deployments/[entity:IdString
deploymentId]/products/[entity:IdString productId], and then update any uses of
deploymentId or productId in the function body to the IdString type if necessary
(e.g., any type assertions, validations, or function calls expecting
entity:IdString).

2206-2208: patch cases/[string caseId]/call-requests/[string callRequestId] not migrated to entity:IdString.

Same inconsistency as the other PATCH endpoints — the case ID and call request ID path parameters still use string.

Proposed fix
-    resource function patch cases/[string caseId]/call\-requests/[string callRequestId](http:RequestContext ctx,
+    resource function patch cases/[entity:IdString caseId]/call\-requests/[entity:IdString callRequestId](http:RequestContext ctx,
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/customer-portal/backend/service.bal` around lines 2206 - 2208, The PATCH
resource signature patch cases/[string caseId]/call-requests/[string
callRequestId] still uses plain string path params; update the route parameter
types to entity:IdString (i.e., change [string caseId] and [string
callRequestId] to [entity:IdString caseId] and [entity:IdString callRequestId]
in the resource function declaration for patch cases/.../call-requests/...) and
adjust any code inside the resource that assumes plain string (e.g., validations
or conversions) to accept entity:IdString; ensure the resource continues to
return
entity:UpdatedCallRequest|http:BadRequest|http:Forbidden|http:NotFound|http:InternalServerError.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@apps/customer-portal/backend/modules/entity/types.bal`:
- Around line 1069-1089: Update the doc comment for the searchQuery field inside
the ConversationSearchPayload type: change the phrase "Search query for chat
messages" to "Search query for conversation messages" (the field is filters ->
searchQuery on ConversationSearchPayload) so the comment matches the renamed
domain term; leave the rest of the record unchanged.

In `@apps/customer-portal/backend/service.bal`:
- Around line 673-678: The comments use stale "chat" terminology; update them to
accurately describe conversation/project statistics. Change the inline comment
before the call to entity:getConversationStatsForProject and the trailing
comment after the error handling around the conversationStats variable to refer
to "conversation" or "project conversation" stats (e.g., "Fetch project
conversation stats" and "To return other project stats even if conversation
stats retrieval fails, error will not be returned"), leaving the call to
entity:getConversationStatsForProject and the error logging via
ERR_MSG_CHATS_STATISTICS unchanged.
- Around line 518-524: Update stale "chat" wording to "conversation" in this
block and related symbols: change the inline comments around
entity:getConversationStatsForProject and the comment at the end of the error
branch to reference "conversation stats" instead of "chat stats", and rename the
constant ERR_MSG_CHATS_STATISTICS to ERR_MSG_CONVERSATIONS_STATISTICS (and
update all usages, e.g., the occurrences noted around lines 673, 677-678) so the
log call log:printError(ERR_MSG_CHATS_STATISTICS, conversationStats) uses the
new constant name; ensure all references and the constant definition are updated
for consistency.

---

Outside diff comments:
In `@apps/customer-portal/backend/modules/entity/types.bal`:
- Around line 447-455: Update the stale doc comment for the
ProjectConversationStatsResponse record: change the comment on the activeCount
field that currently reads "Active chat count" to "Active conversation count" so
it matches the renamed type; locate the ProjectConversationStatsResponse type
and modify the comment above activeCount accordingly.

In `@apps/customer-portal/backend/service.bal`:
- Around line 1050-1078: Change the resource function signature and docs to use
lowercase id of type entity:IdString (resource function get
projects/[entity:IdString id]/conversations/[string conversationId]) and update
the doc comment from "Id" to "id"; rename all uses of Id to id (including the
ai_chat_agent:getChatHistory call). After extracting userInfo
(authorization:UserInfoPayload|error userInfo =
ctx.getWithType(authorization:HEADER_USER_INFO)), call the same project-access
verification used by other project-scoped endpoints (the existing helper used
elsewhere to return 401/403) and return http:Unauthorized or http:Forbidden as
appropriate before calling ai_chat_agent:getChatHistory; keep the existing error
logging (ERR_MSG_USER_INFO_HEADER_NOT_FOUND and log:printError) and preserve the
InternalServerError path for getChatHistory failures.

---

Duplicate comments:
In `@apps/customer-portal/backend/modules/entity/entity.bal`:
- Around line 68-77: The function getConversationStatsForProject and its call to
csEntityClient->/projects/[id]/conversations/stats.get(generateHeaders(idToken))
are already correct and the documentation matches the behavior, so no code
changes are required—leave the function name, endpoint path, and return type
ProjectConversationStatsResponse|error as-is.

In `@apps/customer-portal/backend/modules/entity/types.bal`:
- Around line 1091-1112: The Conversation record's doc comments still refer to
"chat" rather than "conversation"; update the comments for the Conversation type
and its fields (e.g., the IdString id, string? number, string? initialMessage,
and string createdBy entries inside the Conversation record) to use
"conversation" (e.g., "ID of the conversation", "Conversation number", "Initial
message of the conversation", "User who created the conversation"); scan the
Conversation record for any other "chat" mentions and replace them to keep the
documentation consistent.
- Around line 362-363: The field name typo was corrected from
"converstaionStates" to "conversationStates" in the ChoiceListItem[]
declaration; update any references to the old symbol (e.g., code that accessed
converstaionStates, serializers, tests, and any JSON mapping) to use
conversationStates so compilation/serialization stays consistent and run tests
to verify no remaining references to the old name remain.

In `@apps/customer-portal/backend/modules/types/types.bal`:
- Around line 763-770: The ConversationResponse type has already been updated to
rename the field from chats to conversations; no code change is required—just
confirm that the new record type ConversationResponse contains Conversation[]
conversations and int totalRecords and that any references to the old chats
field are updated to use conversations (check usages of ConversationResponse and
any serializers/deserializers).

In `@apps/customer-portal/backend/service.bal`:
- Around line 989-1048: No changes needed: the resource function post
projects/[entity:IdString id]/conversations/search correctly injects the project
id into entity:searchConversations payload (projectIds: [id]) and handles error
cases (Unauthorized, Forbidden, InternalServerError) before returning
mapConversationSearchResponse(conversationResponse); leave these symbols and
logic as-is.

In `@apps/customer-portal/backend/utils.bal`:
- Around line 427-456: The loop variable name `chat` in
mapConversationSearchResponse (declared as `from entity:Conversation chat in
response.conversations`) is a minor readability issue; rename it to a clearer
identifier (e.g., `conversation` or `conv`) in the comprehension and update all
references inside the select block so the mapping logic remains identical but
more descriptive.

---

Nitpick comments:
In `@apps/customer-portal/backend/modules/types/types.bal`:
- Around line 188-198: Rename the stale "chats" fields in the
ProjectSupportStats record to use "Conversations" (change activeChats →
activeConversations, sessionChats → sessionConversations, resolvedChats →
resolvedConversations) and update every place that constructs or reads
ProjectSupportStats (notably where the record is populated in service.bal) to
use the new field names; ensure any serialization/exposed API mappings are
updated to avoid mismatches and run tests to catch any remaining references to
the old field names.
- Around line 200-210: ProjectStats still uses the old field name activeChats;
rename that field to activeConversations in the ProjectStats record definition
(replace activeChats? with activeConversations?) and update every usage site
that references ProjectStats.activeChats — assignments, destructuring, JSON
mapping, and tests — to use ProjectStats.activeConversations so the type and all
consumers reflect the chat→conversation migration consistently.

In `@apps/customer-portal/backend/service.bal`:
- Around line 409-411: The PATCH resource signature uses plain string path
params which bypass hex validation; update the resource declaration resource
function patch projects/[string projectId]/deployments/[string
deploymentId](...) to use the validated type entity:IdString for both path
params (e.g., projects/[entity:IdString projectId]/deployments/[entity:IdString
deploymentId]) so it matches the other endpoints (see resource functions at
lines with entity:IdString) and adjust any local parameter references if
necessary to the same names; no other behavioral changes are required.
- Around line 1391-1393: The resource function signature for patch
deployments/[string deploymentId]/products/[string productId] uses plain string
path parameters; change both path parameter types to entity:IdString to match
other endpoints by updating the resource function declaration (the symbol to
edit is the resource function named "patch deployments/[string
deploymentId]/products/[string productId]") so it reads
deployments/[entity:IdString deploymentId]/products/[entity:IdString productId],
and then update any uses of deploymentId or productId in the function body to
the IdString type if necessary (e.g., any type assertions, validations, or
function calls expecting entity:IdString).
- Around line 2206-2208: The PATCH resource signature patch cases/[string
caseId]/call-requests/[string callRequestId] still uses plain string path
params; update the route parameter types to entity:IdString (i.e., change
[string caseId] and [string callRequestId] to [entity:IdString caseId] and
[entity:IdString callRequestId] in the resource function declaration for patch
cases/.../call-requests/...) and adjust any code inside the resource that
assumes plain string (e.g., validations or conversions) to accept
entity:IdString; ensure the resource continues to return
entity:UpdatedCallRequest|http:BadRequest|http:Forbidden|http:NotFound|http:InternalServerError.

Comment thread apps/customer-portal/backend/modules/entity/types.bal
Comment thread apps/customer-portal/backend/service.bal Outdated
Comment thread apps/customer-portal/backend/service.bal Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (3)
apps/customer-portal/backend/modules/entity/types.bal (1)

447-455: ⚠️ Potential issue | 🟡 Minor

Stale doc comment: # Active chat count should say # Active conversation count.

🔧 Proposed fix
 public type ProjectConversationStatsResponse record {|
-    # Active chat count
+    # Active conversation count
     int activeCount;
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/customer-portal/backend/modules/entity/types.bal` around lines 447 -
455, The doc comment for the activeCount field in the
ProjectConversationStatsResponse record is stale; change the comment from "#
Active chat count" to "# Active conversation count" so the field documentation
accurately describes activeCount in ProjectConversationStatsResponse.
apps/customer-portal/backend/service.bal (1)

1114-1142: ⚠️ Potential issue | 🟡 Minor

[string Id] and [string conversationId] are inconsistent with the PR-wide [entity:IdString id] refactor.

This endpoint is the only conversation-scoped endpoint still using unconstrained string path parameters. Additionally, Id (capital I) deviates from the lowercase id convention used everywhere else in the service.

🔧 Proposed fix
-    resource function get projects/[string Id]/conversations/[string conversationId](http:RequestContext ctx)
+    resource function get projects/[entity:IdString id]/conversations/[entity:IdString conversationId](http:RequestContext ctx)

Also update the doc comment parameter name to match:

-    # + Id - ID of the project
+    # + id - ID of the project
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/customer-portal/backend/service.bal` around lines 1114 - 1142, The path
params on the resource function get projects/[string Id]/conversations/[string
conversationId] are inconsistent with the PR-wide refactor and casing: change
both path parameters to use the constrained type and lowercase names (e.g.,
[entity:IdString id] and [entity:IdString conversationId]), update every use
inside the function (replace Id and conversationId usages with the new lowercase
id and conversationId variables), and update the doc comment parameter names to
match the new lowercase identifiers.
apps/customer-portal/backend/modules/types/types.bal (1)

188-210: ⚠️ Potential issue | 🟡 Minor

activeChats/sessionChats/resolvedChats in public stats types are inconsistent with the chat→conversation rename.

ProjectSupportStats and ProjectStats still expose fields named activeChats, sessionChats, and resolvedChats, but they are now populated from entity:ProjectConversationStatsResponse (e.g., conversationStats.activeCount). If this is intended as a deliberate backward-compat hold-out for the stats API surface, it should be documented; otherwise these should be renamed to activeConversations, sessionConversations, and resolvedConversations for consistency.

🔧 Proposed rename
 public type ProjectSupportStats record {|
     int totalCases?;
-    int activeChats?;
-    int sessionChats?;
-    int resolvedChats?;
+    int activeConversations?;
+    int sessionConversations?;
+    int resolvedConversations?;
 |};

 public type ProjectStats record {|
     int openCases?;
-    int activeChats?;
+    int activeConversations?;
     int deployments?;
     string slaStatus?;
 |};

(Service layer references at lines 610, 748–753 of service.bal would also need updating.)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/customer-portal/backend/modules/types/types.bal` around lines 188 - 210,
The public record types ProjectSupportStats and ProjectStats expose fields named
activeChats, sessionChats, and resolvedChats which are inconsistent with the
internal rename from "chat" to "conversation"; rename those fields to
activeConversations, sessionConversations, and resolvedConversations in the
types (ProjectSupportStats and ProjectStats), update all code that populates
them from entity:ProjectConversationStatsResponse (e.g., map
conversationStats.activeCount → activeConversations, sessionCount →
sessionConversations, resolvedCount → resolvedConversations), and update any
service-layer references and serializers that read/write those fields; if this
was intentionally kept for backward compatibility, instead add clear
documentation and maintain aliasing mapping when serializing/deserializing.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Outside diff comments:
In `@apps/customer-portal/backend/modules/entity/types.bal`:
- Around line 447-455: The doc comment for the activeCount field in the
ProjectConversationStatsResponse record is stale; change the comment from "#
Active chat count" to "# Active conversation count" so the field documentation
accurately describes activeCount in ProjectConversationStatsResponse.

In `@apps/customer-portal/backend/modules/types/types.bal`:
- Around line 188-210: The public record types ProjectSupportStats and
ProjectStats expose fields named activeChats, sessionChats, and resolvedChats
which are inconsistent with the internal rename from "chat" to "conversation";
rename those fields to activeConversations, sessionConversations, and
resolvedConversations in the types (ProjectSupportStats and ProjectStats),
update all code that populates them from entity:ProjectConversationStatsResponse
(e.g., map conversationStats.activeCount → activeConversations, sessionCount →
sessionConversations, resolvedCount → resolvedConversations), and update any
service-layer references and serializers that read/write those fields; if this
was intentionally kept for backward compatibility, instead add clear
documentation and maintain aliasing mapping when serializing/deserializing.

In `@apps/customer-portal/backend/service.bal`:
- Around line 1114-1142: The path params on the resource function get
projects/[string Id]/conversations/[string conversationId] are inconsistent with
the PR-wide refactor and casing: change both path parameters to use the
constrained type and lowercase names (e.g., [entity:IdString id] and
[entity:IdString conversationId]), update every use inside the function (replace
Id and conversationId usages with the new lowercase id and conversationId
variables), and update the doc comment parameter names to match the new
lowercase identifiers.

---

Duplicate comments:
In `@apps/customer-portal/backend/modules/entity/types.bal`:
- Around line 1091-1112: Update the stale "chat" wording in the Conversation
type's field doc comments: replace "chat" with "conversation" for the IdString
id, string? number, string? initialMessage, and string createdBy fields in the
Conversation record so comments read e.g. "ID of the conversation",
"Conversation number", "Initial message of the conversation", and "User who
created the conversation"; edit the doc comment lines inside the public type
Conversation declaration to apply these exact wording changes.

Comment thread apps/customer-portal/backend/modules/entity/entity.bal
Comment thread apps/customer-portal/backend/modules/entity/entity.bal
chanukaranaba
chanukaranaba previously approved these changes Feb 22, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
apps/customer-portal/backend/modules/entity/types.bal (1)

447-455: ⚠️ Potential issue | 🟡 Minor

ProjectConversationStatsResponse is missing json...; and has stale "chat" comment.

Two issues:

  1. The doc comment on line 449 still says "Active chat count" — should be "Active conversation count".
  2. This is the only stats response type using a closed record without a json...; rest field. Both ProjectCaseStatsResponse and ProjectDeploymentStatsResponse include json...; for forward compatibility. This should be consistent.
Proposed fix
 # Project conversation statistics response.
 public type ProjectConversationStatsResponse record {|
-    # Active chat count
+    # Active conversation count
     int activeCount;
     # Session count
     int sessionCount;
     # Resolved count
     int resolvedCount;
+    json...;
 |};
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/customer-portal/backend/modules/entity/types.bal` around lines 447 -
455, Update ProjectConversationStatsResponse: change the doc comment "Active
chat count" to "Active conversation count" and make the record open for forward
compatibility by adding the json...; rest field. Locate the declaration of the
ProjectConversationStatsResponse type and replace the stale comment string and
add the json...; rest field to match ProjectCaseStatsResponse and
ProjectDeploymentStatsResponse.
apps/customer-portal/backend/service.bal (1)

1114-1142: ⚠️ Potential issue | 🟠 Major

Chat history endpoint is inconsistent with the PR-wide IdString refactor and naming conventions.

Three issues with this endpoint:

  1. PascalCase Id (line 1119): The path parameter is [string Id] while every other endpoint uses lowercase [... id].
  2. Missing entity:IdString: Both Id and conversationId remain plain string, skipping the validation that all other refactored endpoints now get.
  3. Missing Unauthorized/Forbidden handling: Unlike the sibling conversation search endpoint (line 1058), this endpoint only handles InternalServerError.
Proposed fix
-    resource function get projects/[string Id]/conversations/[string conversationId](http:RequestContext ctx)
-        returns ai_chat_agent:ChatHistoryResponse|http:InternalServerError {
+    resource function get projects/[entity:IdString id]/conversations/[entity:IdString conversationId](http:RequestContext ctx)
+        returns ai_chat_agent:ChatHistoryResponse|http:Unauthorized|http:Forbidden|http:InternalServerError {

Also update the internal call on line 1131:

-            ai_chat_agent:getChatHistory(Id, conversationId);
+            ai_chat_agent:getChatHistory(id, conversationId);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/customer-portal/backend/service.bal` around lines 1114 - 1142, Update
the resource signature and error handling to match the PR-wide IdString refactor
and sibling endpoints: change the route param `[string Id]` to lowercase
`[string id]`, change both parameters' types from plain string to the validated
type `entity:IdString` (i.e., resource function get projects/[string
id]/conversations/[entity:IdString conversationId] or both as entity:IdString as
per project convention), ensure you still obtain userInfo via
ctx.getWithType(authorization:HEADER_USER_INFO) and add the same
Unauthorized/Forbidden checks and responses used in the sibling conversation
search endpoint, and update the internal call to
ai_chat_agent:getChatHistory(...) to pass the renamed/typed variables (id and
conversationId) accordingly while keeping existing InternalServerError handling
for backend failures.
🧹 Nitpick comments (2)
apps/customer-portal/backend/service.bal (1)

409-411: Deployment update endpoint still uses [string projectId] and [string deploymentId].

This PATCH projects/{projectId}/deployments/{deploymentId} endpoint was not migrated to entity:IdString, while the sibling GET (line 314) and POST (line 353) endpoints for the same resource were. This creates an inconsistency where some deployment routes validate IDs and others don't.

Proposed fix
-    resource function patch projects/[string projectId]/deployments/[string deploymentId](http:RequestContext ctx,
+    resource function patch projects/[entity:IdString projectId]/deployments/[entity:IdString deploymentId](http:RequestContext ctx,
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/customer-portal/backend/service.bal` around lines 409 - 411, The PATCH
resource function declaration "resource function patch projects/[string
projectId]/deployments/[string deploymentId]" should be changed to use the
validated ID type used elsewhere: replace both "[string projectId]" and "[string
deploymentId]" with "[entity:IdString projectId]" and "[entity:IdString
deploymentId]" respectively so the signature matches the GET and POST endpoints;
update any references inside the function body that assume plain strings (e.g.,
uses of projectId or deploymentId) if necessary to work with entity:IdString.
Ensure the resource function name and return types (resource function patch ...
returns ...) remain unchanged other than the parameter type adjustments.
apps/customer-portal/backend/modules/ai_chat_agent/types.bal (1)

29-32: Minor: trailing semicolon after enum closing brace.

The Role enum ends with }; (line 32) while all enums in enums.bal end with just }. This is syntactically valid but inconsistent within the PR.

Proposed fix
 public enum Role {
     USER = "user",
     ASSISTANT = "assistant"
-};
+}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/customer-portal/backend/modules/ai_chat_agent/types.bal` around lines 29
- 32, Trailing semicolon after the Role enum creates an inconsistency with other
enums; open the enum declaration for Role in types.bal (the public enum Role {
USER = "user", ASSISTANT = "assistant" }) and remove the trailing semicolon
after the closing brace so it ends with just } to match the rest of enums in
enums.bal.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@apps/customer-portal/backend/modules/entity/constants.bal`:
- Around line 30-32: The constants ACTIVE and RESOLVED in constants.bal
currently reuse numeric IDs that overlap case states (ACTIVE = 2, RESOLVED = 3)
and are unused; add or update conversation state validation and filtering so
conversation updates use type-based validation rather than relying on unique
numeric values. Specifically, implement a validateConversationUpdatePayload (or
extend existing validateCaseUpdatePayload) to check incoming updates against
conversationStates (not caseStates) and ensure any state comparisons in the
codebase reference the conversation type before interpreting numeric IDs; keep
ACTIVE and RESOLVED if they map to backend conversation IDs but ensure all state
checks use the conversationStates enum/lookup to avoid conflating cases and
conversations.

In `@apps/customer-portal/backend/modules/entity/enums.bal`:
- Around line 46-49: Rename the enum members in ConversationSortField from
CHAT_CREATED_ON and CHAT_UPDATED_ON to CREATED_ON and UPDATED_ON (keeping their
string values "createdOn" and "updatedOn") so the naming matches CaseSortField;
update any references/usages of ConversationSortField.CHAT_CREATED_ON and
ConversationSortField.CHAT_UPDATED_ON to ConversationSortField.CREATED_ON and
ConversationSortField.UPDATED_ON respectively to avoid breakages.

In `@apps/customer-portal/backend/service.bal`:
- Around line 746-754: Rename the response fields returned where
ProjectConversationStatsResponse is used: change activeChats →
activeConversations, sessionChats → sessionConversations, and resolvedChats →
resolvedConversations in the returned object; then update the
ProjectSupportStats type definition to use those same field names and update any
entity/type comments that currently read "Active chat count"/similar to "Active
conversation count" to keep naming consistent with
ProjectConversationStatsResponse. Locate the return object (the block that
references ProjectConversationStatsResponse) and the ProjectSupportStats type
and edit both field names and their comments accordingly so callers and types
align.

---

Outside diff comments:
In `@apps/customer-portal/backend/modules/entity/types.bal`:
- Around line 447-455: Update ProjectConversationStatsResponse: change the doc
comment "Active chat count" to "Active conversation count" and make the record
open for forward compatibility by adding the json...; rest field. Locate the
declaration of the ProjectConversationStatsResponse type and replace the stale
comment string and add the json...; rest field to match ProjectCaseStatsResponse
and ProjectDeploymentStatsResponse.

In `@apps/customer-portal/backend/service.bal`:
- Around line 1114-1142: Update the resource signature and error handling to
match the PR-wide IdString refactor and sibling endpoints: change the route
param `[string Id]` to lowercase `[string id]`, change both parameters' types
from plain string to the validated type `entity:IdString` (i.e., resource
function get projects/[string id]/conversations/[entity:IdString conversationId]
or both as entity:IdString as per project convention), ensure you still obtain
userInfo via ctx.getWithType(authorization:HEADER_USER_INFO) and add the same
Unauthorized/Forbidden checks and responses used in the sibling conversation
search endpoint, and update the internal call to
ai_chat_agent:getChatHistory(...) to pass the renamed/typed variables (id and
conversationId) accordingly while keeping existing InternalServerError handling
for backend failures.

---

Duplicate comments:
In `@apps/customer-portal/backend/modules/entity/types.bal`:
- Around line 1152-1173: Update the doc comments inside the Conversation record
type to replace stale "chat" wording with "conversation": edit the comment lines
for fields id, number, initialMessage and createdBy (the comments currently
saying "ID of the chat", "Chat number", "Initial message of the chat", and "User
who created the chat") to use "conversation" instead so the Conversation type's
field comments are consistent with the rename.

---

Nitpick comments:
In `@apps/customer-portal/backend/modules/ai_chat_agent/types.bal`:
- Around line 29-32: Trailing semicolon after the Role enum creates an
inconsistency with other enums; open the enum declaration for Role in types.bal
(the public enum Role { USER = "user", ASSISTANT = "assistant" }) and remove the
trailing semicolon after the closing brace so it ends with just } to match the
rest of enums in enums.bal.

In `@apps/customer-portal/backend/service.bal`:
- Around line 409-411: The PATCH resource function declaration "resource
function patch projects/[string projectId]/deployments/[string deploymentId]"
should be changed to use the validated ID type used elsewhere: replace both
"[string projectId]" and "[string deploymentId]" with "[entity:IdString
projectId]" and "[entity:IdString deploymentId]" respectively so the signature
matches the GET and POST endpoints; update any references inside the function
body that assume plain strings (e.g., uses of projectId or deploymentId) if
necessary to work with entity:IdString. Ensure the resource function name and
return types (resource function patch ... returns ...) remain unchanged other
than the parameter type adjustments.

Comment thread apps/customer-portal/backend/modules/entity/constants.bal
Comment thread apps/customer-portal/backend/modules/entity/enums.bal
Comment thread apps/customer-portal/backend/service.bal
@chanukaranaba
chanukaranaba merged commit 444e9b1 into wso2-open-operations:customer-portal-milestone-1 Feb 22, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

App/Customer Portal Area/Backend Type/Improvement Marks enhancements or improvements to existing features

Projects

Status: Staging Deployed

Development

Successfully merging this pull request may close these issues.

4 participants