diff --git a/apps/api-gateway/src/ecosystem/ecosystem.controller.ts b/apps/api-gateway/src/ecosystem/ecosystem.controller.ts index f182e362b..9383cd857 100755 --- a/apps/api-gateway/src/ecosystem/ecosystem.controller.ts +++ b/apps/api-gateway/src/ecosystem/ecosystem.controller.ts @@ -813,7 +813,7 @@ export class EcosystemController { description: 'Template details fetched successfully' }) async getTemplateByIntentId( - @Param( + @Param( 'orgId', TrimStringParamPipe, new ParseUUIDPipe({ @@ -944,4 +944,26 @@ export class EcosystemController { data: intent }); } + + @Get('/dashboard/summary') + @Roles(OrgRoles.PLATFORM_ADMIN) + @UseGuards(AuthGuard('jwt'), EcosystemRolesGuard) + @ApiBearerAuth() + @ApiOperation({ + summary: 'Get Count for Ecosystem dashboard', + description: 'Get Count for Ecosystem dashboard' + }) + @ApiResponse({ + status: HttpStatus.OK, + description: 'Dashboard count fetched successfully' + }) + async getDashboardCountEcosystem(@Res() res: Response): Promise { + const dashboard = await this.ecosystemService.getDashboardCountEcosystem(); + + return res.status(HttpStatus.OK).json({ + statusCode: HttpStatus.OK, + message: ResponseMessages.ecosystem.success.dashboard, + data: dashboard + }); + } } diff --git a/apps/api-gateway/src/ecosystem/ecosystem.service.ts b/apps/api-gateway/src/ecosystem/ecosystem.service.ts index 57d7e5d0f..26c9e4ac9 100755 --- a/apps/api-gateway/src/ecosystem/ecosystem.service.ts +++ b/apps/api-gateway/src/ecosystem/ecosystem.service.ts @@ -7,7 +7,8 @@ import { IEcosystemDashboard, IEcosystemInvitation, IEcosystemMemberInvitations, - IGetAllOrgs + IGetAllOrgs, + IPlatformDashboardCount } from 'apps/ecosystem/interfaces/ecosystem.interfaces'; import { CreateEcosystemDto } from 'apps/ecosystem/dtos/create-ecosystem-dto'; // eslint-disable-next-line camelcase @@ -40,7 +41,11 @@ export class EcosystemService { * @param userId * @returns All ecosystems from platform */ - async getEcosystems(userId: string, pageDetail: IPaginationSortingDto, orgId:string): Promise> { + async getEcosystems( + userId: string, + pageDetail: IPaginationSortingDto, + orgId: string + ): Promise> { return this.natsClient.sendNatsMessage(this.serviceProxy, 'get-ecosystems', { userId, pageDetail, orgId }); } @@ -229,4 +234,8 @@ export class EcosystemService { userId }); } + + async getDashboardCountEcosystem(): Promise { + return this.natsClient.sendNatsMessage(this.serviceProxy, 'get-platform-admin-dashboard-count', {}); + } } diff --git a/apps/api-gateway/src/platform/platform.controller.ts b/apps/api-gateway/src/platform/platform.controller.ts index a1b860b68..4cc39c3c8 100644 --- a/apps/api-gateway/src/platform/platform.controller.ts +++ b/apps/api-gateway/src/platform/platform.controller.ts @@ -36,6 +36,8 @@ import { OrgRolesGuard } from '../authz/guards/org-roles.guard'; import { CreateEcosystemInvitationDto } from '../ecosystem/dtos/send-ecosystem-invitation'; import { EnableEcosystemDto } from '../ecosystem/dtos/enable-ecosystem'; import { EcosystemFeatureGuard } from '../authz/guards/ecosystem-feature-guard'; +import { PaginationDto } from '@credebl/common/dtos/pagination.dto'; +import { EcosystemRolesGuard } from '../authz/guards/ecosystem-roles.guard'; @Controller('') @UseFilters(CustomExceptionFilter) @@ -269,8 +271,12 @@ export class PlatformController { @Roles(OrgRoles.PLATFORM_ADMIN) @UseGuards(AuthGuard('jwt'), OrgRolesGuard, EcosystemFeatureGuard) @ApiBearerAuth() - async getInvitations(@User() reqUser: user, @Res() res: Response): Promise { - const invitations = await this.platformService.getInvitationsByUserId(reqUser.id); + async getInvitations( + @User() reqUser: user, + @Res() res: Response, + @Query() pageDto: PaginationDto + ): Promise { + const invitations = await this.platformService.getInvitationsByUserId(reqUser.id, pageDto); return res.status(HttpStatus.OK).json({ statusCode: HttpStatus.OK, @@ -308,4 +314,26 @@ export class PlatformController { }; return res.status(HttpStatus.OK).json(finalResponse); } + + @Get('/ecosystem/status') + @ApiOperation({ + summary: 'Get ecosystem enabled/disabled status', + description: 'Get ecosystem enabled/disabled status' + }) + @ApiResponse({ + status: HttpStatus.OK, + description: 'Ecosystem status fetched successfully' + }) + @Roles(OrgRoles.PLATFORM_ADMIN) + @UseGuards(AuthGuard('jwt'), EcosystemRolesGuard) + @ApiBearerAuth() + async getEcosystemEnableStatus(@Res() res: Response): Promise { + const ecosystemStatus = await this.platformService.getEcosystemEnableStatus(); + + return res.status(HttpStatus.OK).json({ + statusCode: HttpStatus.OK, + message: ResponseMessages.ecosystem.success.ecosystemStatus, + data: ecosystemStatus + }); + } } diff --git a/apps/api-gateway/src/platform/platform.service.ts b/apps/api-gateway/src/platform/platform.service.ts index 1c6a084c4..a2cbfbb8a 100644 --- a/apps/api-gateway/src/platform/platform.service.ts +++ b/apps/api-gateway/src/platform/platform.service.ts @@ -8,6 +8,7 @@ import { IPlatformCredDefsData } from '@credebl/common/interfaces/cred-def.inter import { NATSClient } from '@credebl/common/NATSClient'; import { ClientProxy } from '@nestjs/microservices'; import { IEcosystemInvitations } from 'apps/ecosystem/interfaces/ecosystem.interfaces'; +import { IPaginationSortingDto, PaginatedResponse } from '@credebl/common/interfaces/interface'; @Injectable() export class PlatformService extends BaseService { @@ -62,8 +63,14 @@ export class PlatformService extends BaseService { * @param userId * @returns Get invitations */ - async getInvitationsByUserId(userId: string): Promise { - return this.natsClient.sendNatsMessage(this.platformServiceProxy, 'get-ecosystem-invitations-by-user', { userId }); + async getInvitationsByUserId( + userId: string, + pageDetail: IPaginationSortingDto + ): Promise> { + return this.natsClient.sendNatsMessage(this.platformServiceProxy, 'get-ecosystem-invitations-by-user', { + userId, + pageDetail + }); } /** @@ -75,4 +82,8 @@ export class PlatformService extends BaseService { platformAdminId }); } + + async getEcosystemEnableStatus(): Promise { + return this.natsClient.sendNatsMessage(this.platformServiceProxy, 'get-ecosystem-enable-status', {}); + } } diff --git a/apps/ecosystem/interfaces/ecosystem.interfaces.ts b/apps/ecosystem/interfaces/ecosystem.interfaces.ts index 4b795575d..919e62ec7 100755 --- a/apps/ecosystem/interfaces/ecosystem.interfaces.ts +++ b/apps/ecosystem/interfaces/ecosystem.interfaces.ts @@ -70,6 +70,7 @@ export interface IEcosystemInvitations { createdBy: string; organization?: IEcosystemOrg; invitedOrg?: string; + orgStatus?: string; } export interface IEcosystemOrg { @@ -201,6 +202,18 @@ export interface IGetAllOrgUser { username: string | null; } +export interface IGetEcosystemOrgStatus { + ecosystemId: string; + orgId: string; + status: string; +} + export type EcosystemInvitationRoles = OrgRoles.ECOSYSTEM_LEAD | OrgRoles.ECOSYSTEM_MEMBER; export type PrismaExecutor = Prisma.TransactionClient | PrismaClient; + +export interface IPlatformDashboardCount { + ecosystem: number; + invitations: number; + activeOrgs: number; +} diff --git a/apps/ecosystem/repositories/ecosystem.repository.ts b/apps/ecosystem/repositories/ecosystem.repository.ts index a2a817023..afdb47954 100755 --- a/apps/ecosystem/repositories/ecosystem.repository.ts +++ b/apps/ecosystem/repositories/ecosystem.repository.ts @@ -14,6 +14,8 @@ import { IEcosystemDashboard, IEcosystemInvitation, IGetAllOrgs, + IGetEcosystemOrgStatus, + IPlatformDashboardCount, PrismaExecutor } from '../interfaces/ecosystem.interfaces'; import { @@ -93,41 +95,44 @@ export class EcosystemRepository { } async getInvitationsByUserId( - userId: string + userId: string, + pageDetail: IPaginationSortingDto // eslint-disable-next-line camelcase - ): Promise { + ): Promise> { try { - return await this.prisma.ecosystem_invitations.findMany({ - where: { - createdBy: userId - }, - include: { - ecosystem: { - select: { - id: true, - name: true, - description: true, - createDateTime: true + const whereClause = { + createdBy: userId, + deletedAt: null + }; + const [data, count] = await this.prisma.$transaction([ + this.prisma.ecosystem_invitations.findMany({ + where: whereClause, + include: { + ecosystem: { + select: { + id: true, + name: true, + description: true, + createDateTime: true + } + }, + organisation: { + select: { + name: true + } } }, - user: { - select: { - id: true, - firstName: true, - lastName: true, - email: true - } + orderBy: { + createDateTime: 'desc' }, - organisation: { - select: { - name: true - } - } - }, - orderBy: { - createDateTime: 'desc' - } - }); + take: pageDetail.pageSize, + skip: (pageDetail.pageNumber - 1) * pageDetail.pageSize + }), + + this.prisma.ecosystem_invitations.count({ where: whereClause }) + ]); + const totalPages = Math.ceil(count / pageDetail.pageSize); + return { totalPages, data }; } catch (error) { this.logger.error('getInvitationsByUserId error', error); throw new InternalServerErrorException(ResponseMessages.ecosystem.error.fetchInvitationsFailed); @@ -1491,4 +1496,64 @@ export class EcosystemRepository { throw error; } } + + async getEcosystemOrgsByOrgIdAndEcosystemId( + orgId: string[], + ecosystemId: string[] + ): Promise { + try { + return await this.prisma.ecosystem_orgs.findMany({ + where: { + orgId: { in: orgId }, + ecosystemId: { in: ecosystemId }, + deletedAt: null + }, + select: { + orgId: true, + ecosystemId: true, + status: true + } + }); + } catch (error) { + this.logger.error(`getEcosystemOrgsByOrgIdAndEcosystemId error: ${error}`); + throw error; + } + } + + async getDashBoardCountPlatformAdmin(): Promise { + try { + const data = await this.prisma.$transaction([ + this.prisma.ecosystem.count({ where: { deletedAt: null } }), + this.prisma.ecosystem_invitations.count({ + where: { + type: InviteType.ECOSYSTEM, + deletedAt: null + } + }), + this.prisma.ecosystem_orgs.count({ + where: { + status: EcosystemOrgStatus.ACTIVE, + deletedAt: null + } + }) + ]); + const [ecosystem, invitations, activeOrgs] = data; + return { ecosystem, invitations, activeOrgs }; + } catch (error) { + this.logger.error(`getDashBoardCountPlatformAdmin error: ${error}`); + throw error; + } + } + + async getEcosystemEnableStatus(): Promise { + try { + const data = await this.prisma.platform_config.findFirst({ + select: { isEcosystemEnabled: true } + }); + return data?.isEcosystemEnabled ?? false; + } catch (error) { + this.logger.error(`getEcosystemEnableStatus error: ${error}`); + throw error; + } + } } diff --git a/apps/ecosystem/src/ecosystem.controller.ts b/apps/ecosystem/src/ecosystem.controller.ts index 8a6910421..121739dbc 100755 --- a/apps/ecosystem/src/ecosystem.controller.ts +++ b/apps/ecosystem/src/ecosystem.controller.ts @@ -7,7 +7,8 @@ import { IEcosystemInvitation, IEcosystemInvitations, IEcosystemMemberInvitations, - IGetAllOrgs + IGetAllOrgs, + IPlatformDashboardCount } from '../interfaces/ecosystem.interfaces'; import { IIntentTemplateList, @@ -47,8 +48,11 @@ export class EcosystemController { * @returns List of ecosystem invitations */ @MessagePattern({ cmd: 'get-ecosystem-invitations-by-user' }) - async getInvitationsByUserId(payload: { userId: string }): Promise { - return this.ecosystemService.getInvitationsByUserId(payload.userId); + async getInvitationsByUserId(payload: { + userId: string; + pageDetail: IPaginationSortingDto; + }): Promise> { + return this.ecosystemService.getInvitationsByUserId(payload.userId, payload.pageDetail); } /** @@ -325,4 +329,14 @@ export class EcosystemController { }): Promise<{ message: string }> { return this.ecosystemService.updateEcosystemConfig(payload); } + + @MessagePattern({ cmd: 'get-platform-admin-dashboard-count' }) + async getDashboardCountEcosystem(): Promise { + return this.ecosystemService.getDashboardCountEcosystem(); + } + + @MessagePattern({ cmd: 'get-ecosystem-enable-status' }) + async getEcosystemEnableStatus(): Promise { + return this.ecosystemService.getEcosystemEnableStatus(); + } } diff --git a/apps/ecosystem/src/ecosystem.service.ts b/apps/ecosystem/src/ecosystem.service.ts index 464835180..145193226 100755 --- a/apps/ecosystem/src/ecosystem.service.ts +++ b/apps/ecosystem/src/ecosystem.service.ts @@ -33,7 +33,8 @@ import { IEcosystemInvitation, IEcosystemInvitations, IEcosystemMemberInvitations, - IGetAllOrgs + IGetAllOrgs, + IPlatformDashboardCount } from 'apps/ecosystem/interfaces/ecosystem.interfaces'; import { IIntentTemplateList, @@ -156,13 +157,17 @@ export class EcosystemService { return userData; } - async getInvitationsByUserId(userId: string): Promise { + async getInvitationsByUserId( + userId: string, + pageDetail: IPaginationSortingDto + ): Promise> { if (!userId) { throw new BadRequestException('userId missing'); } try { - return await this.ecosystemRepository.getInvitationsByUserId(userId); + const invitations = await this.ecosystemRepository.getInvitationsByUserId(userId, pageDetail); + return invitations; } catch (error) { this.logger.error('getInvitationsByUserId error', error); throw new InternalServerErrorException(ResponseMessages.ecosystem.error.invitationNotFound); @@ -391,8 +396,8 @@ export class EcosystemService { throw new BadRequestException(ResponseMessages.ecosystem.error.alreadyAccepted); } const result = await this.ecosystemRepository.updateEcosystemInvitationStatusByEmail( - orgId, userEmail, + orgId, ecosystemId, status ); @@ -850,4 +855,12 @@ export class EcosystemService { message: ResponseMessages.ecosystem.success.updateEcosystemConfig }; } + + async getDashboardCountEcosystem(): Promise { + return this.ecosystemRepository.getDashBoardCountPlatformAdmin(); + } + + async getEcosystemEnableStatus(): Promise { + return this.ecosystemRepository.getEcosystemEnableStatus(); + } } diff --git a/libs/common/src/response-messages/index.ts b/libs/common/src/response-messages/index.ts index db9e5d9ca..7695b9f5c 100644 --- a/libs/common/src/response-messages/index.ts +++ b/libs/common/src/response-messages/index.ts @@ -198,7 +198,9 @@ export const ResponseMessages = { fetchIntents: 'Ecosystem intents fetched successfully', fetchIntentTemplates: 'Ecosystem intent templates fetched successfully', fetchVerificationTemplates: 'Verification templates fetched successfully', - updateEcosystemConfig: 'Ecosystem configuration updated successfully' + updateEcosystemConfig: 'Ecosystem configuration updated successfully', + dashboard: 'Dashboard data for ecosystem fetched successfully', + ecosystemStatus: 'Ecosystem status fetched successfully' }, error: { featureIsDisabled: `You don't have access to this feature`, diff --git a/libs/prisma-service/prisma/schema.prisma b/libs/prisma-service/prisma/schema.prisma index 072f87a02..1c0a912d6 100755 --- a/libs/prisma-service/prisma/schema.prisma +++ b/libs/prisma-service/prisma/schema.prisma @@ -779,7 +779,7 @@ model ecosystem_orgs { lastChangedDateTime DateTime @default(now()) @db.Timestamptz(6) lastChangedBy String @db.Uuid deletedAt DateTime? @db.Timestamp(6) - userId String @db.Uuid + userId String @db.Uuid ecosystem ecosystem @relation(fields: [ecosystemId], references: [id]) ecosystemRole ecosystem_roles @relation(fields: [ecosystemRoleId], references: [id]) organisation organisation @relation(fields: [orgId], references: [id]) @@ -804,7 +804,8 @@ model ecosystem_invitations { organisation organisation? @relation(fields: [invitedOrg], references: [id]) ecosystem ecosystem? @relation(fields: [ecosystemId], references: [id]) - user user? @relation(fields: [userId], references: [id]) + user user? @relation(fields: [userId], references: [id]) + @@unique([email, ecosystemId, invitedOrg]) }