From f375bac3065ab50ed547978d3dac89418dabe690 Mon Sep 17 00:00:00 2001 From: Rashmika998 Date: Fri, 20 Feb 2026 16:32:04 +0530 Subject: [PATCH 1/8] Add time cards endpoints --- .../backend/modules/entity/entity.bal | 15 ++++- .../backend/modules/entity/types.bal | 52 +++++++++++++++++ .../backend/modules/types/types.bal | 34 +++++++++++ apps/customer-portal/backend/service.bal | 57 +++++++++++++++++++ apps/customer-portal/backend/utils.bal | 23 ++++++++ 5 files changed, 179 insertions(+), 2 deletions(-) diff --git a/apps/customer-portal/backend/modules/entity/entity.bal b/apps/customer-portal/backend/modules/entity/entity.bal index 943f0c54d5..9ef43c3dbd 100644 --- a/apps/customer-portal/backend/modules/entity/entity.bal +++ b/apps/customer-portal/backend/modules/entity/entity.bal @@ -104,7 +104,7 @@ public isolated function createCase(string idToken, CaseCreatePayload payload) r } # Update an existing case. -# +# # + idToken - ID token for authorization # + caseId - Unique ID of the case to be updated # + payload - Case update payload @@ -187,7 +187,7 @@ public isolated function createDeployedProduct(string idToken, DeployedProductCr } # Update a deployed product. -# +# # + idToken - ID token for authorization # + deployedProductId - ID of the deployed product to update # + payload - Deployed product update payload @@ -325,3 +325,14 @@ public isolated function searchProductVersions(string idToken, string productId, return csEntityClient->/products/[productId]/versions/search.post(payload, generateHeaders(idToken)); } + +# Search timecards of a project. +# +# + idToken - ID token for authorization +# + payload - Timecard search payload containing search criteria for timecards +# + return - Timecards response containing matching timecards or error +public isolated function searchTimecards(string idToken, TimeCardSearchPayload payload) + returns TimeCardsResponse|error { + + return csEntityClient->/time\-cards/search.post(payload, generateHeaders(idToken)); +} diff --git a/apps/customer-portal/backend/modules/entity/types.bal b/apps/customer-portal/backend/modules/entity/types.bal index c3fb45ae47..5450ded99f 100644 --- a/apps/customer-portal/backend/modules/entity/types.bal +++ b/apps/customer-portal/backend/modules/entity/types.bal @@ -1077,3 +1077,55 @@ public type ProductVersionsResponse record {| ProductVersion[] versions; json...; // TODO: Add pagination |}; + +# Request payload for searching time cards. +public type TimeCardSearchPayload record {| + # Filter criteria + record { + # List of project IDs to filter + string[] projectIds?; + # Start date for filtering time cards (ISO 8601 format) + string startDate?; + # End date for filtering time cards (ISO 8601 format) + string endDate?; + } filters?; + # Pagination details + Pagination pagination?; +|}; + +# Time card data. +public type TimeCard record {| + # ID + string id; + # Total time logged + decimal totalTime; + # Created date and time + string createdOn; + # Indicates if the time card has billable hours + boolean hasBillable; + # State information (e.g., "Approved", "Submitted") + string state; + # User who approved the time card + ReferenceTableItem? approvedBy; + # Associated project + ReferenceTableItem? project; + # Associated case + CaseAssociatedWithTimeCard? case; + json...; +|}; + +# Time card information associated with a case. +public type CaseAssociatedWithTimeCard record {| + *ReferenceTableItem; + # Case number + string number; +|}; + +# Time cards response. +public type TimeCardsResponse record {| + # List of time cards + TimeCard[] timeCards; + # Total records count + int totalRecords; + *Pagination; +|}; diff --git a/apps/customer-portal/backend/modules/types/types.bal b/apps/customer-portal/backend/modules/types/types.bal index cea2460cd9..4847ec1189 100644 --- a/apps/customer-portal/backend/modules/types/types.bal +++ b/apps/customer-portal/backend/modules/types/types.bal @@ -730,3 +730,37 @@ public type ProductVersionsResponse record {| ProductVersion[] versions; json...; // TODO: Add pagination |}; + +# Time card data. +public type TimeCard record {| + # ID + string id; + # Total time logged + decimal totalTime; + # Created date and time + string createdOn; + # Indicates if the time card has billable hours + boolean hasBillable; + # State information (e.g., "Approved", "Submitted") + string state; + # User who approved the time card + ReferenceItem? approvedBy; + # Associated project + ReferenceItem? project; + # Associated case + record {| + *ReferenceItem; + # Case number + string number; + |}? case; + json...; +|}; + +# Time cards response. +public type TimeCardsResponse record {| + # List of time cards + TimeCard[] timeCards; + # Total records count + int totalRecords; + *entity:Pagination; +|}; diff --git a/apps/customer-portal/backend/service.bal b/apps/customer-portal/backend/service.bal index f2b6bf8306..44abd40500 100644 --- a/apps/customer-portal/backend/service.bal +++ b/apps/customer-portal/backend/service.bal @@ -2116,4 +2116,61 @@ service http:InterceptableService / on new http:Listener(9090, listenerConf) { body: mapProductVersionsResponse(response) }; } + + # Search time cards based on provided filters. + # + # + payload - Time card search payload containing filters and pagination info + # + return - List of time cards matching the criteria or an error + resource function post time\-cards/search(http:RequestContext ctx, entity:TimeCardSearchPayload payload) + returns http:Ok|http:BadRequest|http:Unauthorized|http:Forbidden|http:InternalServerError { + + authorization:UserInfoPayload|error userInfo = ctx.getWithType(authorization:HEADER_USER_INFO); + if userInfo is error { + return { + body: { + message: ERR_MSG_USER_INFO_HEADER_NOT_FOUND + } + }; + } + + entity:TimeCardsResponse|error response = entity:searchTimecards(userInfo.idToken, payload); + if response is error { + if getStatusCode(response) == http:STATUS_BAD_REQUEST { + return { + body: { + message: "Invalid request parameters for searching time cards." + } + }; + } + + if getStatusCode(response) == http:STATUS_UNAUTHORIZED { + log:printWarn(string `User: ${userInfo.userId} is not authorized to access time card information!`); + return { + body: { + message: ERR_MSG_UNAUTHORIZED_ACCESS + } + }; + } + + if getStatusCode(response) == http:STATUS_FORBIDDEN { + log:printWarn(string `Access to time card information is forbidden for user: ${userInfo.userId}`); + return { + body: { + message: "Access to time card information is forbidden for the user!" + } + }; + } + + string customError = "Failed to search time cards."; + log:printError(customError, response); + return { + body: { + message: customError + } + }; + } + return { + body: mapTimeCardSearchResponse(response) + }; + } } diff --git a/apps/customer-portal/backend/utils.bal b/apps/customer-portal/backend/utils.bal index 13233b246f..13ff33cda4 100644 --- a/apps/customer-portal/backend/utils.bal +++ b/apps/customer-portal/backend/utils.bal @@ -416,3 +416,26 @@ public isolated function mapProductVersionsResponse(entity:ProductVersionsRespon }; return {versions}; } + +# Map time cards search response to the desired structure. +# +# + response - Time cards search response from the entity service +# + return - Mapped time cards search response +public isolated function mapTimeCardSearchResponse(entity:TimeCardsResponse response) returns types:TimeCardsResponse { + types:TimeCard[] timeCards = from entity:TimeCard timeCard in response.timeCards + let entity:ReferenceTableItem? approvedBy = timeCard.approvedBy + let entity:ReferenceTableItem? project = timeCard.project + let entity:CaseAssociatedWithTimeCard? case = timeCard.case + select { + id: timeCard.id, + totalTime: timeCard.totalTime, + createdOn: timeCard.createdOn, + hasBillable: timeCard.hasBillable, + state: timeCard.state, + approvedBy: approvedBy != () ? {id: approvedBy.id, label: approvedBy.name} : (), + project: project != () ? {id: project.id, label: project.name} : (), + case: case != () ? {id: case.id, label: case.name, number: case.number} : () + }; + + return {timeCards, totalRecords: response.totalRecords, 'limit: response.'limit, offset: response.offset}; +} From 664f857ec932e6fe0c2ebbb326cd60cd6a779529 Mon Sep 17 00:00:00 2001 From: Rashmika998 Date: Fri, 20 Feb 2026 16:35:10 +0530 Subject: [PATCH 2/8] Update call request update payload --- apps/customer-portal/backend/modules/entity/types.bal | 2 +- apps/customer-portal/backend/modules/types/types.bal | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/customer-portal/backend/modules/entity/types.bal b/apps/customer-portal/backend/modules/entity/types.bal index 5450ded99f..2909b11648 100644 --- a/apps/customer-portal/backend/modules/entity/types.bal +++ b/apps/customer-portal/backend/modules/entity/types.bal @@ -968,7 +968,7 @@ public type CallRequestUpdatePayload record {| # State key int stateKey; # Reason for the update - string? reason; + string reason?; # New preferred UTC times for the call (mandatory when stateKey is 2) Date[] utcTimes?; |}; diff --git a/apps/customer-portal/backend/modules/types/types.bal b/apps/customer-portal/backend/modules/types/types.bal index 4847ec1189..578ba50edc 100644 --- a/apps/customer-portal/backend/modules/types/types.bal +++ b/apps/customer-portal/backend/modules/types/types.bal @@ -700,7 +700,7 @@ public type CallRequestUpdatePayload record {| # State key int stateKey; # Reason for the update - string? reason; + string reason?; # New preferred UTC times for the call (mandatory when stateKey is 2) Date[] utcTimes?; |}; From 2f2587ff09cc4c7ac33c766bd70a7c149d72cf20 Mon Sep 17 00:00:00 2001 From: Rashmika998 Date: Fri, 20 Feb 2026 20:34:37 +0530 Subject: [PATCH 3/8] Add constraints --- .../backend/modules/entity/types.bal | 21 +++++++++++++------ .../backend/modules/entity/utils.bal | 2 +- 2 files changed, 16 insertions(+), 7 deletions(-) diff --git a/apps/customer-portal/backend/modules/entity/types.bal b/apps/customer-portal/backend/modules/entity/types.bal index 2909b11648..face3e6c08 100644 --- a/apps/customer-portal/backend/modules/entity/types.bal +++ b/apps/customer-portal/backend/modules/entity/types.bal @@ -918,14 +918,14 @@ public type CallRequestsResponse record {| json...; |}; -# Date Constraint. +# Date-time constraint. @constraint:String { pattern: { value: re `^\d{4}-(0[1-9]|1[0-2])-(0[1-9]|[12]\d|3[01])T([01]\d|2[0-3]):[0-5]\d(:[0-5]\d(\.\d{1,9})?)?(Z|[+-]([01]\d|2[0-3]):?[0-5]\d)$`, message: "Invalid date provided. Please provide a valid date value." } } -public type Date string; +public type DateTime string; # Request payload for creating a call request. public type CallRequestCreatePayload record {| @@ -935,7 +935,7 @@ public type CallRequestCreatePayload record {| string reason; # Preferred UTC times for the call @constraint:Array {minLength: 1} - Date[] utcTimes; + DateTime[] utcTimes; # Duration in minutes @constraint:Int {minValue: 1} int durationInMinutes; @@ -970,7 +970,7 @@ public type CallRequestUpdatePayload record {| # Reason for the update string reason?; # New preferred UTC times for the call (mandatory when stateKey is 2) - Date[] utcTimes?; + DateTime[] utcTimes?; |}; # Updated call request details. @@ -1078,6 +1078,15 @@ public type ProductVersionsResponse record {| json...; // TODO: Add pagination |}; +# Date. +@constraint:String { + pattern: { + value: re `^\d{4}-(0[1-9]|1[0-2])-(0[1-9]|[12]\d|3[01])$`, + message: "Invalid date format." + } +} +public type Date string; + # Request payload for searching time cards. public type TimeCardSearchPayload record {| # Filter criteria @@ -1085,9 +1094,9 @@ public type TimeCardSearchPayload record {| # List of project IDs to filter string[] projectIds?; # Start date for filtering time cards (ISO 8601 format) - string startDate?; + Date startDate?; # End date for filtering time cards (ISO 8601 format) - string endDate?; + Date endDate?; } filters?; # Pagination details Pagination pagination?; diff --git a/apps/customer-portal/backend/modules/entity/utils.bal b/apps/customer-portal/backend/modules/entity/utils.bal index f2d9043fe2..c9879dbbd7 100644 --- a/apps/customer-portal/backend/modules/entity/utils.bal +++ b/apps/customer-portal/backend/modules/entity/utils.bal @@ -92,7 +92,7 @@ public isolated function validateCallRequestUpdatePayload(CallRequestUpdatePaylo # # + utcTimes - Array of UTC time strings to validate # + return - Error message if any UTC time is invalid or in the past, nil otherwise -public isolated function validateUtcTimes(Date[]? utcTimes) returns string|error? { +public isolated function validateUtcTimes(DateTime[]? utcTimes) returns string|error? { if utcTimes != () { foreach string utcTime in utcTimes { time:Utc input = check time:utcFromString(utcTime); From fcef19074968a2d4716921351eb99d991e3c20f9 Mon Sep 17 00:00:00 2001 From: Rashmika998 Date: Fri, 20 Feb 2026 20:37:46 +0530 Subject: [PATCH 4/8] Update documentation --- apps/customer-portal/backend/modules/entity/entity.bal | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/customer-portal/backend/modules/entity/entity.bal b/apps/customer-portal/backend/modules/entity/entity.bal index 9ef43c3dbd..1656b6224c 100644 --- a/apps/customer-portal/backend/modules/entity/entity.bal +++ b/apps/customer-portal/backend/modules/entity/entity.bal @@ -326,7 +326,7 @@ public isolated function searchProductVersions(string idToken, string productId, return csEntityClient->/products/[productId]/versions/search.post(payload, generateHeaders(idToken)); } -# Search timecards of a project. +# Search timecards. # # + idToken - ID token for authorization # + payload - Timecard search payload containing search criteria for timecards From 5e887acb1c025a9b8376c9ece0780e2f953277f7 Mon Sep 17 00:00:00 2001 From: Rashmika998 Date: Fri, 20 Feb 2026 20:43:55 +0530 Subject: [PATCH 5/8] Update endpoint --- .../backend/modules/types/types.bal | 26 +++++++++++++++++-- apps/customer-portal/backend/service.bal | 14 ++++++++-- 2 files changed, 36 insertions(+), 4 deletions(-) diff --git a/apps/customer-portal/backend/modules/types/types.bal b/apps/customer-portal/backend/modules/types/types.bal index 578ba50edc..ebc1ba5a53 100644 --- a/apps/customer-portal/backend/modules/types/types.bal +++ b/apps/customer-portal/backend/modules/types/types.bal @@ -681,6 +681,15 @@ public type CallRequestsResponse record {| message: "Invalid date provided. Please provide a valid date value." } } +public type DateTime string; + +# Date. +@constraint:String { + pattern: { + value: re `^\d{4}-(0[1-9]|1[0-2])-(0[1-9]|[12]\d|3[01])$`, + message: "Invalid date format." + } +} public type Date string; # Request payload for creating a call request. @@ -689,7 +698,7 @@ public type CallRequestCreatePayload record {| string reason; # Preferred UTC times for the call @constraint:Array {minLength: 1} - Date[] utcTimes; + DateTime[] utcTimes; # Duration in minutes @constraint:Int {minValue: 1} int durationInMinutes; @@ -702,7 +711,7 @@ public type CallRequestUpdatePayload record {| # Reason for the update string reason?; # New preferred UTC times for the call (mandatory when stateKey is 2) - Date[] utcTimes?; + DateTime[] utcTimes?; |}; # Product version data. @@ -764,3 +773,16 @@ public type TimeCardsResponse record {| int totalRecords; *entity:Pagination; |}; + +# Request payload for searching time cards. +public type TimeCardSearchPayload record {| + # Filter criteria + record { + # Start date for filtering time cards (ISO 8601 format) + Date startDate?; + # End date for filtering time cards (ISO 8601 format) + Date endDate?; + } filters?; + # Pagination details + entity:Pagination pagination?; +|}; diff --git a/apps/customer-portal/backend/service.bal b/apps/customer-portal/backend/service.bal index 44abd40500..2846838a10 100644 --- a/apps/customer-portal/backend/service.bal +++ b/apps/customer-portal/backend/service.bal @@ -2119,9 +2119,11 @@ service http:InterceptableService / on new http:Listener(9090, listenerConf) { # Search time cards based on provided filters. # + # + id - ID of the project # + payload - Time card search payload containing filters and pagination info # + return - List of time cards matching the criteria or an error - resource function post time\-cards/search(http:RequestContext ctx, entity:TimeCardSearchPayload payload) + resource function post projects/[string id]/time\-cards/search(http:RequestContext ctx, + types:TimeCardSearchPayload payload) returns http:Ok|http:BadRequest|http:Unauthorized|http:Forbidden|http:InternalServerError { authorization:UserInfoPayload|error userInfo = ctx.getWithType(authorization:HEADER_USER_INFO); @@ -2133,7 +2135,15 @@ service http:InterceptableService / on new http:Listener(9090, listenerConf) { }; } - entity:TimeCardsResponse|error response = entity:searchTimecards(userInfo.idToken, payload); + entity:TimeCardsResponse|error response = entity:searchTimecards(userInfo.idToken, + { + filters: { + projectIds: [id], + startDate: payload.filters?.startDate, + endDate: payload.filters?.endDate + }, + pagination: payload.pagination + }); if response is error { if getStatusCode(response) == http:STATUS_BAD_REQUEST { return { From d7aee82c193890616d3427b5a7ab2ed40341e743 Mon Sep 17 00:00:00 2001 From: Rashmika998 Date: Fri, 20 Feb 2026 20:47:27 +0530 Subject: [PATCH 6/8] Update date-time documentation --- apps/customer-portal/backend/modules/entity/types.bal | 2 +- apps/customer-portal/backend/modules/types/types.bal | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/customer-portal/backend/modules/entity/types.bal b/apps/customer-portal/backend/modules/entity/types.bal index face3e6c08..142e7a5bef 100644 --- a/apps/customer-portal/backend/modules/entity/types.bal +++ b/apps/customer-portal/backend/modules/entity/types.bal @@ -918,7 +918,7 @@ public type CallRequestsResponse record {| json...; |}; -# Date-time constraint. +# Date-time (UTC). @constraint:String { pattern: { value: re `^\d{4}-(0[1-9]|1[0-2])-(0[1-9]|[12]\d|3[01])T([01]\d|2[0-3]):[0-5]\d(:[0-5]\d(\.\d{1,9})?)?(Z|[+-]([01]\d|2[0-3]):?[0-5]\d)$`, diff --git a/apps/customer-portal/backend/modules/types/types.bal b/apps/customer-portal/backend/modules/types/types.bal index ebc1ba5a53..218f7dcb35 100644 --- a/apps/customer-portal/backend/modules/types/types.bal +++ b/apps/customer-portal/backend/modules/types/types.bal @@ -674,7 +674,7 @@ public type CallRequestsResponse record {| // TODO: Remove after adding pagination |}; -# Date Constraint. +# Date-time (UTC). @constraint:String { pattern: { value: re `^\d{4}-(0[1-9]|1[0-2])-(0[1-9]|[12]\d|3[01])T([01]\d|2[0-3]):[0-5]\d(:[0-5]\d(\.\d{1,9})?)?(Z|[+-]([01]\d|2[0-3]):?[0-5]\d)$`, From 05dd0db3ba7cbd8fcaf40210e1d9b6586bf83ecc Mon Sep 17 00:00:00 2001 From: Rashmika998 Date: Sat, 21 Feb 2026 10:29:58 +0530 Subject: [PATCH 7/8] Reuse entity types for types module --- .../backend/modules/entity/entity.bal | 8 +++--- .../backend/modules/types/types.bal | 26 +++---------------- apps/customer-portal/backend/service.bal | 2 +- 3 files changed, 9 insertions(+), 27 deletions(-) diff --git a/apps/customer-portal/backend/modules/entity/entity.bal b/apps/customer-portal/backend/modules/entity/entity.bal index 1656b6224c..0df85e3f16 100644 --- a/apps/customer-portal/backend/modules/entity/entity.bal +++ b/apps/customer-portal/backend/modules/entity/entity.bal @@ -326,12 +326,12 @@ public isolated function searchProductVersions(string idToken, string productId, return csEntityClient->/products/[productId]/versions/search.post(payload, generateHeaders(idToken)); } -# Search timecards. +# Search time cards. # # + idToken - ID token for authorization -# + payload - Timecard search payload containing search criteria for timecards -# + return - Timecards response containing matching timecards or error -public isolated function searchTimecards(string idToken, TimeCardSearchPayload payload) +# + payload - Payload containing search criteria for time cards +# + return - Response containing matching time cards or error +public isolated function searchTimeCards(string idToken, TimeCardSearchPayload payload) returns TimeCardsResponse|error { return csEntityClient->/time\-cards/search.post(payload, generateHeaders(idToken)); diff --git a/apps/customer-portal/backend/modules/types/types.bal b/apps/customer-portal/backend/modules/types/types.bal index 218f7dcb35..1cb9f8c37c 100644 --- a/apps/customer-portal/backend/modules/types/types.bal +++ b/apps/customer-portal/backend/modules/types/types.bal @@ -674,31 +674,13 @@ public type CallRequestsResponse record {| // TODO: Remove after adding pagination |}; -# Date-time (UTC). -@constraint:String { - pattern: { - value: re `^\d{4}-(0[1-9]|1[0-2])-(0[1-9]|[12]\d|3[01])T([01]\d|2[0-3]):[0-5]\d(:[0-5]\d(\.\d{1,9})?)?(Z|[+-]([01]\d|2[0-3]):?[0-5]\d)$`, - message: "Invalid date provided. Please provide a valid date value." - } -} -public type DateTime string; - -# Date. -@constraint:String { - pattern: { - value: re `^\d{4}-(0[1-9]|1[0-2])-(0[1-9]|[12]\d|3[01])$`, - message: "Invalid date format." - } -} -public type Date string; - # Request payload for creating a call request. public type CallRequestCreatePayload record {| # Reason for the call request string reason; # Preferred UTC times for the call @constraint:Array {minLength: 1} - DateTime[] utcTimes; + entity:DateTime[] utcTimes; # Duration in minutes @constraint:Int {minValue: 1} int durationInMinutes; @@ -711,7 +693,7 @@ public type CallRequestUpdatePayload record {| # Reason for the update string reason?; # New preferred UTC times for the call (mandatory when stateKey is 2) - DateTime[] utcTimes?; + entity:DateTime[] utcTimes?; |}; # Product version data. @@ -779,9 +761,9 @@ public type TimeCardSearchPayload record {| # Filter criteria record { # Start date for filtering time cards (ISO 8601 format) - Date startDate?; + entity:Date startDate?; # End date for filtering time cards (ISO 8601 format) - Date endDate?; + entity:Date endDate?; } filters?; # Pagination details entity:Pagination pagination?; diff --git a/apps/customer-portal/backend/service.bal b/apps/customer-portal/backend/service.bal index 2846838a10..3ff9f2b809 100644 --- a/apps/customer-portal/backend/service.bal +++ b/apps/customer-portal/backend/service.bal @@ -2135,7 +2135,7 @@ service http:InterceptableService / on new http:Listener(9090, listenerConf) { }; } - entity:TimeCardsResponse|error response = entity:searchTimecards(userInfo.idToken, + entity:TimeCardsResponse|error response = entity:searchTimeCards(userInfo.idToken, { filters: { projectIds: [id], From fdb96812afe2192fd4134b2fde9ce9341fd67598 Mon Sep 17 00:00:00 2001 From: Rashmika998 Date: Sat, 21 Feb 2026 10:39:25 +0530 Subject: [PATCH 8/8] Rename the case record of time card --- apps/customer-portal/backend/modules/entity/types.bal | 4 ++-- apps/customer-portal/backend/utils.bal | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/apps/customer-portal/backend/modules/entity/types.bal b/apps/customer-portal/backend/modules/entity/types.bal index 142e7a5bef..1e1069af66 100644 --- a/apps/customer-portal/backend/modules/entity/types.bal +++ b/apps/customer-portal/backend/modules/entity/types.bal @@ -1119,12 +1119,12 @@ public type TimeCard record {| # Associated project ReferenceTableItem? project; # Associated case - CaseAssociatedWithTimeCard? case; + TimeCardCase? case; json...; |}; # Time card information associated with a case. -public type CaseAssociatedWithTimeCard record {| +public type TimeCardCase record {| *ReferenceTableItem; # Case number string number; diff --git a/apps/customer-portal/backend/utils.bal b/apps/customer-portal/backend/utils.bal index 13ff33cda4..8cff44da04 100644 --- a/apps/customer-portal/backend/utils.bal +++ b/apps/customer-portal/backend/utils.bal @@ -425,7 +425,7 @@ public isolated function mapTimeCardSearchResponse(entity:TimeCardsResponse resp types:TimeCard[] timeCards = from entity:TimeCard timeCard in response.timeCards let entity:ReferenceTableItem? approvedBy = timeCard.approvedBy let entity:ReferenceTableItem? project = timeCard.project - let entity:CaseAssociatedWithTimeCard? case = timeCard.case + let entity:TimeCardCase? case = timeCard.case select { id: timeCard.id, totalTime: timeCard.totalTime,