diff --git a/apps/api-server/internal/graphql/schema.graphql b/apps/api-server/internal/graphql/schema.graphql new file mode 100644 index 0000000..9ab3da3 --- /dev/null +++ b/apps/api-server/internal/graphql/schema.graphql @@ -0,0 +1,483 @@ +scalar DateTime +scalar JSON + +enum SubscriberStatus { + ACTIVE + INACTIVE + SUSPENDED + TERMINATED + PROVISIONING +} + +enum ProfileStatus { + ACTIVE + INACTIVE + DOWNLOADING + FAILED +} + +enum UsageType { + DATA + VOICE + SMS +} + +enum SessionStatus { + ACTIVE + COMPLETED + TERMINATED +} + +enum PaymentMethodType { + CREDIT_CARD + BANK_ACCOUNT +} + +enum InvoiceStatus { + DRAFT + PENDING + PAID + OVERDUE + CANCELLED +} + +enum AlertType { + LOW_BALANCE + HIGH_USAGE + PAYMENT_FAILED + SYSTEM_ERROR +} + +enum AlertSeverity { + LOW + MEDIUM + HIGH + CRITICAL +} + +type Subscriber { + id: ID! + imsi: String! + msisdn: String! + firstName: String! + lastName: String! + email: String! + organizationId: String + planId: Int! + euiccId: String + profileId: String + profileStatus: ProfileStatus! + status: SubscriberStatus! + balance: Float! + dataLimit: Float! + dataUsed: Float! + voiceLimit: Float! + voiceUsed: Float! + smsLimit: Float! + smsUsed: Float! + createdAt: DateTime! + updatedAt: DateTime! + + account: SubscriberAccount! + usageEvents(first: Int, after: String, filter: UsageEventFilter): UsageEventConnection! + invoices(first: Int, after: String, status: InvoiceStatus): InvoiceConnection! + alerts(first: Int, after: String, severity: AlertSeverity): AlertConnection! + ratingPlan: RatingPlan! +} + +type SubscriberAccount { + imsi: String! + balance: Float! + dataLimit: Float! + dataUsed: Float! + voiceLimit: Float! + voiceUsed: Float! + smsLimit: Float! + smsUsed: Float! + status: SubscriberStatus! + lastUpdated: DateTime! +} + +type UsageEvent { + id: ID! + imsi: String! + sessionId: String! + usageType: UsageType! + volume: Float! + timestamp: DateTime! + rate: Float! + cost: Float! + + subscriber: Subscriber! +} + +type RatingPlan { + planId: String! + name: String! + dataRate: Float! + voiceRate: Float! + smsRate: Float! + monthlyFee: Float! + dataLimit: Float! + voiceLimit: Float! + smsLimit: Float! + + subscribers(first: Int, after: String, status: SubscriberStatus): SubscriberConnection! +} + +type ChargingSession { + sessionId: String! + imsi: String! + startTime: DateTime! + endTime: DateTime + dataBytes: Float! + voiceSeconds: Float! + smsCount: Float! + totalCost: Float! + status: SessionStatus! + + subscriber: Subscriber! + usageEvents(first: Int, after: String): UsageEventConnection! +} + +type PaymentMethod { + id: String! + type: PaymentMethodType! + last4: String! + expiryMonth: Int! + expiryYear: Int! + brand: String! + isDefault: Boolean! +} + +type Invoice { + id: String! + subscriberId: Int! + amount: Float! + currency: String! + status: InvoiceStatus! + dueDate: DateTime! + createdAt: DateTime! + lineItems: [InvoiceLineItem!]! + + subscriber: Subscriber! +} + +type InvoiceLineItem { + description: String! + quantity: Int! + unitPrice: Float! + amount: Float! +} + +type Alert { + id: String! + type: AlertType! + severity: AlertSeverity! + message: String! + subscriberId: Int + timestamp: DateTime! + resolved: Boolean! + + subscriber: Subscriber +} + +type SystemStats { + activeSessions: Int! + totalAccounts: Int! + blockedUsers: Int! + lowBalanceAlerts: Int! + uptime: Float! +} + +type HealthStatus { + redisConnected: Boolean! + activeSync: Boolean! + lastSync: DateTime! + memoryUsage: Float! +} + +type SubscriberConnection { + edges: [SubscriberEdge!]! + pageInfo: PageInfo! + totalCount: Int! +} + +type SubscriberEdge { + node: Subscriber! + cursor: String! +} + +type UsageEventConnection { + edges: [UsageEventEdge!]! + pageInfo: PageInfo! + totalCount: Int! +} + +type UsageEventEdge { + node: UsageEvent! + cursor: String! +} + +type InvoiceConnection { + edges: [InvoiceEdge!]! + pageInfo: PageInfo! + totalCount: Int! +} + +type InvoiceEdge { + node: Invoice! + cursor: String! +} + +type AlertConnection { + edges: [AlertEdge!]! + pageInfo: PageInfo! + totalCount: Int! +} + +type AlertEdge { + node: Alert! + cursor: String! +} + +type PageInfo { + hasNextPage: Boolean! + hasPreviousPage: Boolean! + startCursor: String + endCursor: String +} + +type SubscriberFilter { + status: SubscriberStatus + organizationId: String + planId: Int + search: String + balanceMin: Float + balanceMax: Float + dataUsageMin: Float + dataUsageMax: Float +} + +type UsageEventFilter { + usageType: UsageType + timestampGte: DateTime + timestampLte: DateTime + costMin: Float + costMax: Float +} + +type CreateSubscriberInput { + msisdn: String! + firstName: String! + lastName: String! + email: String! + organizationId: String + planId: Int! + euiccId: String +} + +type UpdateSubscriberInput { + firstName: String + lastName: String + email: String + organizationId: String + planId: Int +} + +type TopUpInput { + amount: Float! + paymentMethodId: String +} + +type UsageStatsInput { + imsi: String! + period: UsagePeriod! +} + +enum UsagePeriod { + DAILY + WEEKLY + MONTHLY + YEARLY +} + +type Query { + subscriber(id: ID!): Subscriber + subscriberByImsi(imsi: String!): Subscriber + subscribers( + first: Int + after: String + filter: SubscriberFilter + sort: SubscriberSort + ): SubscriberConnection! + + subscriberAccount(imsi: String!): SubscriberAccount + + usageEvents( + first: Int + after: String + imsi: String + filter: UsageEventFilter + ): UsageEventConnection! + usageStats(input: UsageStatsInput!): UsageStats! + realtimeUsage(imsi: String!): RealTimeUsage! + + invoices( + first: Int + after: String + imsi: String + status: InvoiceStatus + ): InvoiceConnection! + invoice(id: String!): Invoice + + ratingPlans: [RatingPlan!]! + ratingPlan(planId: String!): RatingPlan + + chargingSessions( + first: Int + after: String + imsi: String + status: SessionStatus + ): ChargingSessionConnection! + chargingSession(sessionId: String!): ChargingSession + + alerts( + first: Int + after: String + subscriberId: Int + severity: AlertSeverity + resolved: Boolean + ): AlertConnection! + + systemStats: SystemStats! + healthStatus: HealthStatus! + + searchSubscribers(query: String!, limit: Int): [Subscriber!]! + searchUsageEvents(query: String!, limit: Int): [UsageEvent!]! +} + +type Mutation { + createSubscriber(input: CreateSubscriberInput!): Subscriber! + updateSubscriber(id: ID!, input: UpdateSubscriberInput!): Subscriber! + deleteSubscriber(id: ID!): Boolean! + + topUpBalance(imsi: String!, input: TopUpInput!): SubscriberAccount! + + suspendSubscriber(id: ID!): Subscriber! + activateSubscriber(id: ID!): Subscriber! + terminateSubscriber(id: ID!): Subscriber! + + provisionESIM(imsi: String!): ESIMProvisionResult! + activateESIM(imsi: String!, profileId: String!): Boolean! + deactivateESIM(imsi: String!, profileId: String!): Boolean! + + addPaymentMethod(subscriberId: Int!, input: PaymentMethodInput!): PaymentMethod! + removePaymentMethod(paymentMethodId: String!): Boolean! + setDefaultPaymentMethod(paymentMethodId: String!): PaymentMethod! + addPaymentMethod(subscriberId: Int!, input: PaymentMethodInput!): PaymentMethod! + removePaymentMethod(paymentMethodId: String!): Boolean! + setDefaultPaymentMethod(paymentMethodId: String!): PaymentMethod! + + resolveAlert(alertId: String!): Alert! + createAlert(input: CreateAlertInput!): Alert! + + triggerSystemMaintenance: Boolean! +} + +type Subscription { + # Real-time subscriptions + subscriberUpdates(subscriberId: ID!): Subscriber! + usageUpdates(imsi: String!): UsageEvent! + alertUpdates(severity: AlertSeverity): Alert! + systemStatsUpdates: SystemStats! +} + +type UsageStats { + dataUsage: Float! + voiceUsage: Float! + smsUsage: Float! + cost: Float! + period: String! + trend: UsageTrend! +} + +type UsageTrend { + direction: TrendDirection! + percentage: Float! + periodOverPeriod: Float! +} + +enum TrendDirection { + UP + DOWN + STABLE +} + +type RealTimeUsage { + currentSession: CurrentSession + todayUsage: TodayUsage! +} + +type CurrentSession { + sessionId: String! + startTime: DateTime! + dataUsed: Float! + voiceUsed: Float! + smsUsed: Float! + cost: Float! +} + +type TodayUsage { + dataUsed: Float! + voiceUsed: Float! + smsUsed: Float! + cost: Float! +} + +type ESIMProvisionResult { + profileId: String! + activationCode: String! + qrCode: String! +} + +type PaymentMethodInput { + type: PaymentMethodType! + token: String! + isDefault: Boolean +} + +type CreateAlertInput { + type: AlertType! + severity: AlertSeverity! + message: String! + subscriberId: Int +} + +type ChargingSessionConnection { + edges: [ChargingSessionEdge!]! + pageInfo: PageInfo! + totalCount: Int! +} + +type ChargingSessionEdge { + node: ChargingSession! + cursor: String! +} + +enum SubscriberSort { + CREATED_AT_ASC + CREATED_AT_DESC + UPDATED_AT_ASC + UPDATED_AT_DESC + FIRST_NAME_ASC + FIRST_NAME_DESC + LAST_NAME_ASC + LAST_NAME_DESC + EMAIL_ASC + EMAIL_DESC + BALANCE_ASC + BALANCE_DESC + DATA_USED_ASC + DATA_USED_DESC +}