Files
nutcas3 1889e78db2 feat: Refactor SubscriberService to split monolithic service into modular files with method organization by domain
- Remove all method implementations from subscriber.go (CreateSubscriber/GetSubscriber/GetSubscriberByIMSI/UpdateSubscriber/SuspendSubscriber/TerminateSubscriber/ListSubscribers/terminateSubscriberSessions/GetAccount/ListInvoices/GetInvoice/ListRatingPlans/GetRatingPlan/ListAlerts/SearchSubscribers/ResolveAlert/CreateAlert and all other methods)
- Update SubscriberService struct comment
2026-04-24 08:51:13 +03:00

103 lines
3.0 KiB
Go

package services
import (
"context"
"fmt"
"strconv"
"time"
"github.com/nutcas3/telecom-platform/apps/api-server/internal/models"
)
// ListAlerts lists alerts with optional filtering by subscriber, severity, and resolved status.
func (s *SubscriberService) ListAlerts(ctx context.Context, limit int, offset int, subscriberId *int, severity *models.AlertSeverity, resolved *bool) ([]*models.Alert, int64, error) {
query := s.db.DB.WithContext(ctx).Model(&models.Alert{})
if subscriberId != nil {
query = query.Where("subscriber_id = ?", *subscriberId)
}
if severity != nil {
query = query.Where("severity = ?", *severity)
}
if resolved != nil {
query = query.Where("resolved = ?", *resolved)
}
var total int64
if err := query.Count(&total).Error; err != nil {
return nil, 0, err
}
var alerts []*models.Alert
if err := query.Preload("Subscriber").Limit(limit).Offset(offset).
Order("timestamp DESC").Find(&alerts).Error; err != nil {
return nil, 0, err
}
return alerts, total, nil
}
// SearchSubscribers searches subscribers by name, MSISDN, or IMSI.
func (s *SubscriberService) SearchSubscribers(ctx context.Context, query string, limit int) ([]*models.Subscriber, error) {
var subscribers []*models.Subscriber
searchPattern := "%" + query + "%"
if err := s.db.DB.WithContext(ctx).
Where("first_name ILIKE ? OR last_name ILIKE ? OR msisdn ILIKE ? OR imsi ILIKE ?",
searchPattern, searchPattern, searchPattern, searchPattern).
Limit(limit).
Find(&subscribers).Error; err != nil {
return nil, fmt.Errorf("failed to search subscribers: %w", err)
}
return subscribers, nil
}
// ResolveAlert marks an alert as resolved.
func (s *SubscriberService) ResolveAlert(ctx context.Context, alertId string) (*models.Alert, error) {
alertID, err := strconv.ParseUint(alertId, 10, 32)
if err != nil {
return nil, fmt.Errorf("invalid alert ID: %w", err)
}
var alert models.Alert
if err := s.db.DB.WithContext(ctx).
Model(&alert).
Where("id = ?", alertID).
Update("resolved", true).
Update("resolved_at", time.Now()).
Error; err != nil {
return nil, fmt.Errorf("failed to resolve alert: %w", err)
}
if err := s.db.DB.WithContext(ctx).
Preload("Subscriber").
First(&alert, alertID).Error; err != nil {
return nil, fmt.Errorf("alert not found: %w", err)
}
return &alert, nil
}
// CreateAlert creates a new alert for a subscriber.
func (s *SubscriberService) CreateAlert(ctx context.Context, req *models.CreateAlertRequest) (*models.Alert, error) {
alert := &models.Alert{
Type: req.Type,
Severity: req.Severity,
Message: req.Message,
SubscriberID: req.SubscriberID,
Timestamp: time.Now(),
Resolved: false,
}
if err := s.db.DB.WithContext(ctx).Create(alert).Error; err != nil {
return nil, fmt.Errorf("failed to create alert: %w", err)
}
if err := s.db.DB.WithContext(ctx).
Preload("Subscriber").
First(alert, alert.ID).Error; err != nil {
return nil, fmt.Errorf("failed to retrieve created alert: %w", err)
}
return alert, nil
}