From a3e98f0a15e2c5e864fc1c1b45ab80d4637c547c Mon Sep 17 00:00:00 2001 From: Rashmika998 Date: Mon, 9 Feb 2026 18:02:30 +0530 Subject: [PATCH 1/9] Add products and deployments fetch endpoints --- .../backend/modules/entity/entity.bal | 18 ++++ .../backend/modules/entity/types.bal | 59 ++++++++++++ apps/customer-portal/backend/service.bal | 93 +++++++++++++++++++ apps/customer-portal/backend/types.bal | 28 +++++- apps/customer-portal/backend/utils.bal | 19 +++- 5 files changed, 215 insertions(+), 2 deletions(-) diff --git a/apps/customer-portal/backend/modules/entity/entity.bal b/apps/customer-portal/backend/modules/entity/entity.bal index c9fa461c8f..997650d082 100644 --- a/apps/customer-portal/backend/modules/entity/entity.bal +++ b/apps/customer-portal/backend/modules/entity/entity.bal @@ -124,3 +124,21 @@ public isolated function searchAttachments(string idToken, ReferenceSearchPayloa return csEntityClient->/attachments/search.post(payload, generateHeaders(idToken)); } + +# Get products of a deployment. +# +# + idToken - ID token for authorization +# + deploymentId - ID of the deployment +# + return - Products response or error +public isolated function getProducts(string idToken, string deploymentId) returns ProductsResponse|error { + return csEntityClient->/products/search.get(generateHeaders(idToken), deploymentId = deploymentId); +} + +# Get deployments of a project. +# +# + idToken - ID token for authorization +# + projectId - ID of the project +# + return - Deployments response or error +public isolated function getDeployments(string idToken, string projectId) returns DeploymentsResponse|error { + return csEntityClient->/deployments/search.post(generateHeaders(idToken), projectId = projectId); +} diff --git a/apps/customer-portal/backend/modules/entity/types.bal b/apps/customer-portal/backend/modules/entity/types.bal index 7e9de8947f..4abbaeadad 100644 --- a/apps/customer-portal/backend/modules/entity/types.bal +++ b/apps/customer-portal/backend/modules/entity/types.bal @@ -394,3 +394,62 @@ public type AttachmentsResponse record {| int totalRecords; *Pagination; |}; + +# Product data. +public type Product record {| + # ID + string id; + # Created date and time + string createdOn; + # Updated date and time + string updatedOn; + # Description + string? description; + # Number of cores + string? cores; + # Transactions per second + string? tps; + # Update level + string? updateLevel; + # Associated deployment + ReferenceTableItem? deployment; + # Product model information + ReferenceTableItem? productModel; + json...; +|}; + +# Products response. +public type ProductsResponse record {| + # List of products + Product[] products; + # Total records count + int totalRecords; + *Pagination; +|}; + +# Deployment data. +public type Deployment record {| + # ID + string id; + # Name + string name; + # Created date and time + string createdOn; + # Updated date and time + string updatedOn; + # Description + string? description; + # URL + string? url; + # Associated project + ReferenceTableItem? project; + # Type + ChoiceListItem? 'type; + json...; +|}; + +# Deployments response. +public type DeploymentsResponse record {| + # List of deployments + Deployment[] deployments; +|}; diff --git a/apps/customer-portal/backend/service.bal b/apps/customer-portal/backend/service.bal index 65e9210524..50201bfebd 100644 --- a/apps/customer-portal/backend/service.bal +++ b/apps/customer-portal/backend/service.bal @@ -302,6 +302,99 @@ service http:InterceptableService / on new http:Listener(9090) { return projectResponse; } + # Get deployments of a project by ID. + # + # + id - ID of the project + # + return - Deployments response or error response + resource function get projects/[string id]/deployments(http:RequestContext ctx) + returns DeploymentsResponse|http:BadRequest|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 + } + }; + } + + if isEmptyId(id) { + return { + body: { + message: ERR_MSG_PROJECT_ID_EMPTY + } + }; + } + + entity:DeploymentsResponse|error deploymentsResponse = entity:getDeployments(userInfo.idToken, id); + if deploymentsResponse is error { + if getStatusCode(deploymentsResponse) == http:STATUS_FORBIDDEN { + logForbiddenProjectAccess(id, userInfo.userId); + return { + body: { + message: ERR_MSG_PROJECT_ACCESS_FORBIDDEN + } + }; + } + + string customError = "Failed to retrieve deployments for the project."; + log:printError(customError, deploymentsResponse); + return { + body: { + message: customError + } + }; + } + return getDeployments(deploymentsResponse); + } + + # Get products of a deployment by project ID and deployment ID. + # + # + projectId - ID of the project + # + deploymentId - ID of the deployment + # + return - Products response or error response + resource function get projects/[string projectId]/deployments/[string deploymentId](http:RequestContext ctx) + returns entity:ProductsResponse|http:BadRequest|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 + } + }; + } + + if isEmptyId(projectId) || isEmptyId(deploymentId) { + return { + body: { + message: "Project ID and Deployment ID cannot be empty!" + } + }; + } + + entity:ProductsResponse|error productsResponse = entity:getProducts(userInfo.idToken, deploymentId); + if productsResponse is error { + if getStatusCode(productsResponse) == http:STATUS_FORBIDDEN { + logForbiddenProjectAccess(projectId, userInfo.userId); + return { + body: { + message: ERR_MSG_PROJECT_ACCESS_FORBIDDEN + } + }; + } + + string customError = "Failed to retrieve products for the deployment."; + log:printError(customError, productsResponse); + return { + body: { + message: customError + } + }; + } + return productsResponse; + } + # Get overall project statistics by ID. # # + id - ID of the project diff --git a/apps/customer-portal/backend/types.bal b/apps/customer-portal/backend/types.bal index 697ea28707..e4f374547b 100644 --- a/apps/customer-portal/backend/types.bal +++ b/apps/customer-portal/backend/types.bal @@ -185,7 +185,7 @@ public type RecentActivity record {| # Last deployment date string? lastDeploymentOn; # System health status - string systemHealth; + string systemHealth; |}; # Project statistics response. @@ -247,3 +247,29 @@ public type AttachmentsResponse record {| int totalRecords; *entity:Pagination; |}; + +# Deployment data. +public type Deployment record {| + # ID + string id; + # Name + string name; + # Created date and time + string createdOn; + # Updated date and time + string updatedOn; + # Description + string? description; + # URL + string? url; + # Associated project + ReferenceItem? project; + # Type + ReferenceItem? 'type; +|}; + +# Deployments response. +public type DeploymentsResponse record {| + # List of deployments + Deployment[] deployments; +|}; diff --git a/apps/customer-portal/backend/utils.bal b/apps/customer-portal/backend/utils.bal index 2ae17f441e..a656e67dc0 100644 --- a/apps/customer-portal/backend/utils.bal +++ b/apps/customer-portal/backend/utils.bal @@ -161,7 +161,7 @@ public function isInvalidLimitOffset(int? 'limit, int? offset) returns boolean = ('limit != () && ('limit < 1 || 'limit > 50)) || (offset != () && offset < 0); # Map attachments response to map to desired structure. -# +# # + response - Attachments response from the entity service # + return - Mapped attachments response public isolated function mapAttachmentsResponse(entity:AttachmentsResponse response) returns AttachmentsResponse { @@ -183,3 +183,20 @@ public isolated function mapAttachmentsResponse(entity:AttachmentsResponse respo offset: response.offset }; } + +public isolated function getDeployments(entity:DeploymentsResponse response) returns DeploymentsResponse { + Deployment[] deployments = from entity:Deployment deployment in response.deployments + let entity:ReferenceTableItem? project = deployment.project + let entity:ChoiceListItem? 'type = deployment.'type + select { + id: deployment.id, + name: deployment.name, + createdOn: deployment.createdOn, + updatedOn: deployment.updatedOn, + description: deployment.description, + url: deployment.url, + project: project != () ? {id: project.id, label: project.name} : (), + 'type: 'type != () ? {id: 'type.id.toString(), label: 'type.label} : () + }; + return {deployments}; +} From dbfdeb17b20312fd55a6462067a3a418baf77877 Mon Sep 17 00:00:00 2001 From: Rashmika998 Date: Tue, 10 Feb 2026 11:46:37 +0530 Subject: [PATCH 2/9] Refactor code --- .../backend/modules/entity/entity.bal | 8 ++++-- .../backend/modules/entity/types.bal | 23 ++++++--------- apps/customer-portal/backend/service.bal | 19 +++++++------ apps/customer-portal/backend/types.bal | 24 ++++++++++++++++ apps/customer-portal/backend/utils.bal | 28 ++++++++++++++++++- 5 files changed, 74 insertions(+), 28 deletions(-) diff --git a/apps/customer-portal/backend/modules/entity/entity.bal b/apps/customer-portal/backend/modules/entity/entity.bal index 997650d082..fc870525fd 100644 --- a/apps/customer-portal/backend/modules/entity/entity.bal +++ b/apps/customer-portal/backend/modules/entity/entity.bal @@ -130,8 +130,10 @@ public isolated function searchAttachments(string idToken, ReferenceSearchPayloa # + idToken - ID token for authorization # + deploymentId - ID of the deployment # + return - Products response or error -public isolated function getProducts(string idToken, string deploymentId) returns ProductsResponse|error { - return csEntityClient->/products/search.get(generateHeaders(idToken), deploymentId = deploymentId); +public isolated function getDeployedProducts(string idToken, string deploymentId) + returns DeployedProductsResponse|error { + + return csEntityClient->/deployed\-products/search.post({deploymentId}, generateHeaders(idToken)); } # Get deployments of a project. @@ -140,5 +142,5 @@ public isolated function getProducts(string idToken, string deploymentId) return # + projectId - ID of the project # + return - Deployments response or error public isolated function getDeployments(string idToken, string projectId) returns DeploymentsResponse|error { - return csEntityClient->/deployments/search.post(generateHeaders(idToken), projectId = projectId); + return csEntityClient->/deployments/search.post({filters: {projectIds: [projectId]}}, generateHeaders(idToken)); } diff --git a/apps/customer-portal/backend/modules/entity/types.bal b/apps/customer-portal/backend/modules/entity/types.bal index 4abbaeadad..4419bd9a78 100644 --- a/apps/customer-portal/backend/modules/entity/types.bal +++ b/apps/customer-portal/backend/modules/entity/types.bal @@ -395,22 +395,18 @@ public type AttachmentsResponse record {| *Pagination; |}; -# Product data. -public type Product record {| +# Deployed product data. +public type DeployedProduct record {| # ID string id; + # Name + string name; # Created date and time string createdOn; # Updated date and time string updatedOn; # Description string? description; - # Number of cores - string? cores; - # Transactions per second - string? tps; - # Update level - string? updateLevel; # Associated deployment ReferenceTableItem? deployment; # Product model information @@ -418,13 +414,10 @@ public type Product record {| json...; |}; -# Products response. -public type ProductsResponse record {| - # List of products - Product[] products; - # Total records count - int totalRecords; - *Pagination; +# Deployed products response. +public type DeployedProductsResponse record {| + # List of deployed products + DeployedProduct[] products; |}; # Deployment data. diff --git a/apps/customer-portal/backend/service.bal b/apps/customer-portal/backend/service.bal index 50201bfebd..10c12e8546 100644 --- a/apps/customer-portal/backend/service.bal +++ b/apps/customer-portal/backend/service.bal @@ -303,7 +303,7 @@ service http:InterceptableService / on new http:Listener(9090) { } # Get deployments of a project by ID. - # + # # + id - ID of the project # + return - Deployments response or error response resource function get projects/[string id]/deployments(http:RequestContext ctx) @@ -345,17 +345,17 @@ service http:InterceptableService / on new http:Listener(9090) { } }; } - return getDeployments(deploymentsResponse); + return mapDeployments(deploymentsResponse); } # Get products of a deployment by project ID and deployment ID. - # + # # + projectId - ID of the project # + deploymentId - ID of the deployment # + return - Products response or error response - resource function get projects/[string projectId]/deployments/[string deploymentId](http:RequestContext ctx) - returns entity:ProductsResponse|http:BadRequest|http:Forbidden|http:InternalServerError { - + resource function get projects/[string projectId]/deployments/[string deploymentId]/products(http:RequestContext + ctx) returns DeployedProductsResponse|http:BadRequest|http:Forbidden|http:InternalServerError { + authorization:UserInfoPayload|error userInfo = ctx.getWithType(authorization:HEADER_USER_INFO); if userInfo is error { return { @@ -373,7 +373,8 @@ service http:InterceptableService / on new http:Listener(9090) { }; } - entity:ProductsResponse|error productsResponse = entity:getProducts(userInfo.idToken, deploymentId); + entity:DeployedProductsResponse|error productsResponse = + entity:getDeployedProducts(userInfo.idToken, deploymentId); if productsResponse is error { if getStatusCode(productsResponse) == http:STATUS_FORBIDDEN { logForbiddenProjectAccess(projectId, userInfo.userId); @@ -392,7 +393,7 @@ service http:InterceptableService / on new http:Listener(9090) { } }; } - return productsResponse; + return mapDeployedProducts(productsResponse); } # Get overall project statistics by ID. @@ -869,7 +870,7 @@ service http:InterceptableService / on new http:Listener(9090) { } }; } - + if getStatusCode(caseDetails) == http:STATUS_FORBIDDEN { logForbiddenCaseAccess(id, userInfo.userId); return { diff --git a/apps/customer-portal/backend/types.bal b/apps/customer-portal/backend/types.bal index e4f374547b..5cd27a0c0d 100644 --- a/apps/customer-portal/backend/types.bal +++ b/apps/customer-portal/backend/types.bal @@ -273,3 +273,27 @@ public type DeploymentsResponse record {| # List of deployments Deployment[] deployments; |}; + +# Deployed product data. +public type DeployedProduct record {| + # ID + string id; + # Name + string name; + # Created date and time + string createdOn; + # Updated date and time + string updatedOn; + # Description + string? description; + # Associated product model + ReferenceItem? productModel; + # Deployment + ReferenceItem? deployment; +|}; + +# Deployed product response. +public type DeployedProductsResponse record {| + # List of deployed products + DeployedProduct[] products; +|}; diff --git a/apps/customer-portal/backend/utils.bal b/apps/customer-portal/backend/utils.bal index a656e67dc0..e3c607a3e8 100644 --- a/apps/customer-portal/backend/utils.bal +++ b/apps/customer-portal/backend/utils.bal @@ -184,7 +184,11 @@ public isolated function mapAttachmentsResponse(entity:AttachmentsResponse respo }; } -public isolated function getDeployments(entity:DeploymentsResponse response) returns DeploymentsResponse { +# Map deployments response to the desired structure. +# +# + response - Deployments response from the entity service +# + return - Mapped deployments response +public isolated function mapDeployments(entity:DeploymentsResponse response) returns DeploymentsResponse { Deployment[] deployments = from entity:Deployment deployment in response.deployments let entity:ReferenceTableItem? project = deployment.project let entity:ChoiceListItem? 'type = deployment.'type @@ -200,3 +204,25 @@ public isolated function getDeployments(entity:DeploymentsResponse response) ret }; return {deployments}; } + +# Map deployed products response to the desired structure. +# +# + response - Deployed products response from the entity service +# + return - Mapped deployed products response +public isolated function mapDeployedProducts(entity:DeployedProductsResponse response) + returns DeployedProductsResponse { + + DeployedProduct[] deployedProducts = from entity:DeployedProduct product in response.products + let entity:ReferenceTableItem? productModel = product.productModel + let entity:ReferenceTableItem? deployment = product.deployment + select { + id: product.id, + name: product.name, + createdOn: product.createdOn, + updatedOn: product.updatedOn, + description: product.description, + productModel: productModel != () ? {id: productModel.id, label: productModel.name} : (), + deployment: deployment != () ? {id: deployment.id.toString(), label: deployment.name} : () + }; + return {products: deployedProducts}; +} From 64ccf540bd5798fa10e2483bac3f51d82d149a0d Mon Sep 17 00:00:00 2001 From: Rashmika998 Date: Tue, 10 Feb 2026 12:07:12 +0530 Subject: [PATCH 3/9] Removed unsued mappings --- apps/customer-portal/backend/modules/entity/types.bal | 2 -- apps/customer-portal/backend/types.bal | 2 -- apps/customer-portal/backend/utils.bal | 1 - 3 files changed, 5 deletions(-) diff --git a/apps/customer-portal/backend/modules/entity/types.bal b/apps/customer-portal/backend/modules/entity/types.bal index 4419bd9a78..1bcd61d26b 100644 --- a/apps/customer-portal/backend/modules/entity/types.bal +++ b/apps/customer-portal/backend/modules/entity/types.bal @@ -399,8 +399,6 @@ public type AttachmentsResponse record {| public type DeployedProduct record {| # ID string id; - # Name - string name; # Created date and time string createdOn; # Updated date and time diff --git a/apps/customer-portal/backend/types.bal b/apps/customer-portal/backend/types.bal index 5cd27a0c0d..28914719b8 100644 --- a/apps/customer-portal/backend/types.bal +++ b/apps/customer-portal/backend/types.bal @@ -278,8 +278,6 @@ public type DeploymentsResponse record {| public type DeployedProduct record {| # ID string id; - # Name - string name; # Created date and time string createdOn; # Updated date and time diff --git a/apps/customer-portal/backend/utils.bal b/apps/customer-portal/backend/utils.bal index e3c607a3e8..5b924cf08c 100644 --- a/apps/customer-portal/backend/utils.bal +++ b/apps/customer-portal/backend/utils.bal @@ -217,7 +217,6 @@ public isolated function mapDeployedProducts(entity:DeployedProductsResponse res let entity:ReferenceTableItem? deployment = product.deployment select { id: product.id, - name: product.name, createdOn: product.createdOn, updatedOn: product.updatedOn, description: product.description, From 859f2ee6ab55ca23accdde3a562254a45742125b Mon Sep 17 00:00:00 2001 From: Rashmika998 Date: Tue, 10 Feb 2026 12:13:32 +0530 Subject: [PATCH 4/9] Update resource method --- apps/customer-portal/backend/service.bal | 96 ++++++++++++------------ 1 file changed, 48 insertions(+), 48 deletions(-) diff --git a/apps/customer-portal/backend/service.bal b/apps/customer-portal/backend/service.bal index 10c12e8546..3949dd19ef 100644 --- a/apps/customer-portal/backend/service.bal +++ b/apps/customer-portal/backend/service.bal @@ -348,54 +348,6 @@ service http:InterceptableService / on new http:Listener(9090) { return mapDeployments(deploymentsResponse); } - # Get products of a deployment by project ID and deployment ID. - # - # + projectId - ID of the project - # + deploymentId - ID of the deployment - # + return - Products response or error response - resource function get projects/[string projectId]/deployments/[string deploymentId]/products(http:RequestContext - ctx) returns DeployedProductsResponse|http:BadRequest|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 - } - }; - } - - if isEmptyId(projectId) || isEmptyId(deploymentId) { - return { - body: { - message: "Project ID and Deployment ID cannot be empty!" - } - }; - } - - entity:DeployedProductsResponse|error productsResponse = - entity:getDeployedProducts(userInfo.idToken, deploymentId); - if productsResponse is error { - if getStatusCode(productsResponse) == http:STATUS_FORBIDDEN { - logForbiddenProjectAccess(projectId, userInfo.userId); - return { - body: { - message: ERR_MSG_PROJECT_ACCESS_FORBIDDEN - } - }; - } - - string customError = "Failed to retrieve products for the deployment."; - log:printError(customError, productsResponse); - return { - body: { - message: customError - } - }; - } - return mapDeployedProducts(productsResponse); - } - # Get overall project statistics by ID. # # + id - ID of the project @@ -970,4 +922,52 @@ service http:InterceptableService / on new http:Listener(9090) { } return mapAttachmentsResponse(attachmentResponse); } + + # Get products of a deployment by deployment ID. + # + # + id - ID of the deployment + # + return - Deployed products response or error response + resource function get deployments/[string id]/products(http:RequestContext ctx) + returns DeployedProductsResponse|http:BadRequest|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 + } + }; + } + + if isEmptyId(id) { + return { + body: { + message: "Deployment ID cannot be empty!" + } + }; + } + + entity:DeployedProductsResponse|error productsResponse = + entity:getDeployedProducts(userInfo.idToken, id); + if productsResponse is error { + if getStatusCode(productsResponse) == http:STATUS_FORBIDDEN { + string customeErr = string `Access to deployment ID: ${id} is forbidden for user: ${userInfo.userId}`; + log:printWarn(customeErr); + return { + body: { + message: "Access to the requested deployment is forbidden!" + } + }; + } + + string customError = "Failed to retrieve products for the deployment."; + log:printError(customError, productsResponse); + return { + body: { + message: customError + } + }; + } + return mapDeployedProducts(productsResponse); + } } From 2495fa7ec3b4eb9796011ca873374a67e2b61c89 Mon Sep 17 00:00:00 2001 From: Rashmika998 Date: Tue, 10 Feb 2026 13:48:24 +0530 Subject: [PATCH 5/9] Update deployed products endpoint --- 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 fc870525fd..4505ab693c 100644 --- a/apps/customer-portal/backend/modules/entity/entity.bal +++ b/apps/customer-portal/backend/modules/entity/entity.bal @@ -133,7 +133,7 @@ public isolated function searchAttachments(string idToken, ReferenceSearchPayloa public isolated function getDeployedProducts(string idToken, string deploymentId) returns DeployedProductsResponse|error { - return csEntityClient->/deployed\-products/search.post({deploymentId}, generateHeaders(idToken)); + return csEntityClient->/deployed_products/search.post({deploymentId}, generateHeaders(idToken)); } # Get deployments of a project. From dff0331eea5ec7f68420c318ec60b0f4ed2b1c87 Mon Sep 17 00:00:00 2001 From: Rashmika998 Date: Tue, 10 Feb 2026 13:52:59 +0530 Subject: [PATCH 6/9] Update warn log --- apps/customer-portal/backend/service.bal | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/apps/customer-portal/backend/service.bal b/apps/customer-portal/backend/service.bal index 3949dd19ef..d5d8776e38 100644 --- a/apps/customer-portal/backend/service.bal +++ b/apps/customer-portal/backend/service.bal @@ -951,8 +951,7 @@ service http:InterceptableService / on new http:Listener(9090) { entity:getDeployedProducts(userInfo.idToken, id); if productsResponse is error { if getStatusCode(productsResponse) == http:STATUS_FORBIDDEN { - string customeErr = string `Access to deployment ID: ${id} is forbidden for user: ${userInfo.userId}`; - log:printWarn(customeErr); + log:printWarn(string `Access to deployment ID: ${id} is forbidden for user: ${userInfo.userId}`); return { body: { message: "Access to the requested deployment is forbidden!" From a8efcb9ef9cb10e8c77c6a0b6e8c2ea4302369f9 Mon Sep 17 00:00:00 2001 From: Rashmika998 Date: Tue, 10 Feb 2026 23:26:59 +0530 Subject: [PATCH 7/9] Update response types --- apps/customer-portal/backend/Dependencies.toml | 3 +-- apps/customer-portal/backend/service.bal | 2 +- apps/customer-portal/backend/utils.bal | 6 +++--- 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/apps/customer-portal/backend/Dependencies.toml b/apps/customer-portal/backend/Dependencies.toml index 16f0d06cf3..d838f29c48 100644 --- a/apps/customer-portal/backend/Dependencies.toml +++ b/apps/customer-portal/backend/Dependencies.toml @@ -348,7 +348,6 @@ modules = [ {org = "wso2", packageName = "customer_portal", moduleName = "customer_portal"}, {org = "wso2", packageName = "customer_portal", moduleName = "customer_portal.authorization"}, {org = "wso2", packageName = "customer_portal", moduleName = "customer_portal.entity"}, - {org = "wso2", packageName = "customer_portal", moduleName = "customer_portal.scim"}, - {org = "wso2", packageName = "customer_portal", moduleName = "customer_portal.types"} + {org = "wso2", packageName = "customer_portal", moduleName = "customer_portal.scim"} ] diff --git a/apps/customer-portal/backend/service.bal b/apps/customer-portal/backend/service.bal index d5d8776e38..49159d9a57 100644 --- a/apps/customer-portal/backend/service.bal +++ b/apps/customer-portal/backend/service.bal @@ -928,7 +928,7 @@ service http:InterceptableService / on new http:Listener(9090) { # + id - ID of the deployment # + return - Deployed products response or error response resource function get deployments/[string id]/products(http:RequestContext ctx) - returns DeployedProductsResponse|http:BadRequest|http:Forbidden|http:InternalServerError { + returns DeployedProduct[]|http:BadRequest|http:Forbidden|http:InternalServerError { authorization:UserInfoPayload|error userInfo = ctx.getWithType(authorization:HEADER_USER_INFO); if userInfo is error { diff --git a/apps/customer-portal/backend/utils.bal b/apps/customer-portal/backend/utils.bal index 5b924cf08c..1a707a9f31 100644 --- a/apps/customer-portal/backend/utils.bal +++ b/apps/customer-portal/backend/utils.bal @@ -210,7 +210,7 @@ public isolated function mapDeployments(entity:DeploymentsResponse response) ret # + response - Deployed products response from the entity service # + return - Mapped deployed products response public isolated function mapDeployedProducts(entity:DeployedProductsResponse response) - returns DeployedProductsResponse { + returns DeployedProduct[] { DeployedProduct[] deployedProducts = from entity:DeployedProduct product in response.products let entity:ReferenceTableItem? productModel = product.productModel @@ -221,7 +221,7 @@ public isolated function mapDeployedProducts(entity:DeployedProductsResponse res updatedOn: product.updatedOn, description: product.description, productModel: productModel != () ? {id: productModel.id, label: productModel.name} : (), - deployment: deployment != () ? {id: deployment.id.toString(), label: deployment.name} : () + deployment: deployment != () ? {id: deployment.id, label: deployment.name} : () }; - return {products: deployedProducts}; + return deployedProducts; } From 8892128bafec483baf4c3695d9aa8f296c02d8bc Mon Sep 17 00:00:00 2001 From: Rashmika998 Date: Tue, 10 Feb 2026 23:47:25 +0530 Subject: [PATCH 8/9] Refactor code --- apps/customer-portal/backend/service.bal | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/customer-portal/backend/service.bal b/apps/customer-portal/backend/service.bal index 49159d9a57..90e8c32fa4 100644 --- a/apps/customer-portal/backend/service.bal +++ b/apps/customer-portal/backend/service.bal @@ -307,7 +307,7 @@ service http:InterceptableService / on new http:Listener(9090) { # + id - ID of the project # + return - Deployments response or error response resource function get projects/[string id]/deployments(http:RequestContext ctx) - returns DeploymentsResponse|http:BadRequest|http:Forbidden|http:InternalServerError { + returns Deployment[]|http:BadRequest|http:Forbidden|http:InternalServerError { authorization:UserInfoPayload|error userInfo = ctx.getWithType(authorization:HEADER_USER_INFO); if userInfo is error { From cae9ac08bdeddbdb75d65ed0211b15950df5fd58 Mon Sep 17 00:00:00 2001 From: Rashmika998 Date: Tue, 10 Feb 2026 23:48:03 +0530 Subject: [PATCH 9/9] Optimize code --- .../backend/modules/entity/entity.bal | 2 +- .../backend/modules/entity/types.bal | 6 +++--- apps/customer-portal/backend/types.bal | 18 +++--------------- apps/customer-portal/backend/utils.bal | 12 +++++------- 4 files changed, 12 insertions(+), 26 deletions(-) diff --git a/apps/customer-portal/backend/modules/entity/entity.bal b/apps/customer-portal/backend/modules/entity/entity.bal index 4505ab693c..fc870525fd 100644 --- a/apps/customer-portal/backend/modules/entity/entity.bal +++ b/apps/customer-portal/backend/modules/entity/entity.bal @@ -133,7 +133,7 @@ public isolated function searchAttachments(string idToken, ReferenceSearchPayloa public isolated function getDeployedProducts(string idToken, string deploymentId) returns DeployedProductsResponse|error { - return csEntityClient->/deployed_products/search.post({deploymentId}, generateHeaders(idToken)); + return csEntityClient->/deployed\-products/search.post({deploymentId}, generateHeaders(idToken)); } # Get deployments of a project. diff --git a/apps/customer-portal/backend/modules/entity/types.bal b/apps/customer-portal/backend/modules/entity/types.bal index 1bcd61d26b..e26f27a697 100644 --- a/apps/customer-portal/backend/modules/entity/types.bal +++ b/apps/customer-portal/backend/modules/entity/types.bal @@ -407,15 +407,15 @@ public type DeployedProduct record {| string? description; # Associated deployment ReferenceTableItem? deployment; - # Product model information - ReferenceTableItem? productModel; + # Product information + ReferenceTableItem? product; json...; |}; # Deployed products response. public type DeployedProductsResponse record {| # List of deployed products - DeployedProduct[] products; + DeployedProduct[] deployedProducts; |}; # Deployment data. diff --git a/apps/customer-portal/backend/types.bal b/apps/customer-portal/backend/types.bal index 28914719b8..552b2b25b9 100644 --- a/apps/customer-portal/backend/types.bal +++ b/apps/customer-portal/backend/types.bal @@ -248,7 +248,7 @@ public type AttachmentsResponse record {| *entity:Pagination; |}; -# Deployment data. +# Deployment information. public type Deployment record {| # ID string id; @@ -268,12 +268,6 @@ public type Deployment record {| ReferenceItem? 'type; |}; -# Deployments response. -public type DeploymentsResponse record {| - # List of deployments - Deployment[] deployments; -|}; - # Deployed product data. public type DeployedProduct record {| # ID @@ -284,14 +278,8 @@ public type DeployedProduct record {| string updatedOn; # Description string? description; - # Associated product model - ReferenceItem? productModel; + # Associated product + ReferenceItem? product; # Deployment ReferenceItem? deployment; |}; - -# Deployed product response. -public type DeployedProductsResponse record {| - # List of deployed products - DeployedProduct[] products; -|}; diff --git a/apps/customer-portal/backend/utils.bal b/apps/customer-portal/backend/utils.bal index 1a707a9f31..06eed60412 100644 --- a/apps/customer-portal/backend/utils.bal +++ b/apps/customer-portal/backend/utils.bal @@ -188,8 +188,8 @@ public isolated function mapAttachmentsResponse(entity:AttachmentsResponse respo # # + response - Deployments response from the entity service # + return - Mapped deployments response -public isolated function mapDeployments(entity:DeploymentsResponse response) returns DeploymentsResponse { - Deployment[] deployments = from entity:Deployment deployment in response.deployments +public isolated function mapDeployments(entity:DeploymentsResponse response) returns Deployment[] { + return from entity:Deployment deployment in response.deployments let entity:ReferenceTableItem? project = deployment.project let entity:ChoiceListItem? 'type = deployment.'type select { @@ -202,7 +202,6 @@ public isolated function mapDeployments(entity:DeploymentsResponse response) ret project: project != () ? {id: project.id, label: project.name} : (), 'type: 'type != () ? {id: 'type.id.toString(), label: 'type.label} : () }; - return {deployments}; } # Map deployed products response to the desired structure. @@ -212,16 +211,15 @@ public isolated function mapDeployments(entity:DeploymentsResponse response) ret public isolated function mapDeployedProducts(entity:DeployedProductsResponse response) returns DeployedProduct[] { - DeployedProduct[] deployedProducts = from entity:DeployedProduct product in response.products - let entity:ReferenceTableItem? productModel = product.productModel + return from entity:DeployedProduct product in response.deployedProducts + let entity:ReferenceTableItem? associatedProduct = product.product let entity:ReferenceTableItem? deployment = product.deployment select { id: product.id, createdOn: product.createdOn, updatedOn: product.updatedOn, description: product.description, - productModel: productModel != () ? {id: productModel.id, label: productModel.name} : (), + product: associatedProduct != () ? {id: associatedProduct.id, label: associatedProduct.name} : (), deployment: deployment != () ? {id: deployment.id, label: deployment.name} : () }; - return deployedProducts; }