mirror of
https://github.com/andwati/telecom-platform.git
synced 2026-10-18 11:02:54 +00:00
feat: Add MVNO repository with CRUD operations, filtering, and statistics aggregation
- Add MVNORepository implementation with CreateMVNO, GetMVNO, UpdateMVNO, ListMVNOs, DeleteMVNO, and UpdateMVNOStatus methods - Add MVNOFilter struct with status, plan, business_id, limit, offset, and date range filtering - Add GetMVNO and GetMVNOByBusinessID methods with record not found error handling - Add ListMVNOs with dynamic query building, filter application, and descending created_at ordering - Add GetMVNOStats with total count, status distribution, and plan distribution aggregation
This commit is contained in:
@@ -0,0 +1,172 @@
|
||||
package repository
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/nutcas3/telecom-platform/apps/carrier-connector/internal/mvno"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
// MVNOFilter defines filtering options for MVNO queries
|
||||
type MVNOFilter struct {
|
||||
Status mvno.MVNOStatus `json:"status,omitempty"`
|
||||
Plan mvno.MVNOPlan `json:"plan,omitempty"`
|
||||
BusinessID string `json:"business_id,omitempty"`
|
||||
Limit int `json:"limit,omitempty"`
|
||||
Offset int `json:"offset,omitempty"`
|
||||
CreatedAfter *time.Time `json:"created_after,omitempty"`
|
||||
CreatedBefore *time.Time `json:"created_before,omitempty"`
|
||||
}
|
||||
|
||||
// CreateMVNO creates a new MVNO record
|
||||
func (r *GormRepository) CreateMVNO(ctx context.Context, mvno *mvno.MVNO) error {
|
||||
if err := r.db.WithContext(ctx).Create(mvno).Error; err != nil {
|
||||
return fmt.Errorf("failed to create MVNO: %w", err)
|
||||
}
|
||||
|
||||
r.logger.Info("MVNO created", "id", mvno.ID, "business_id", mvno.BusinessID)
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetMVNO retrieves an MVNO by ID
|
||||
func (r *GormRepository) GetMVNO(ctx context.Context, id string) (*mvno.MVNO, error) {
|
||||
var mvno mvno.MVNO
|
||||
if err := r.db.WithContext(ctx).Where("id = ?", id).First(&mvno).Error; err != nil {
|
||||
if err == gorm.ErrRecordNotFound {
|
||||
return nil, fmt.Errorf("MVNO not found: %s", id)
|
||||
}
|
||||
return nil, fmt.Errorf("failed to get MVNO: %w", err)
|
||||
}
|
||||
return &mvno, nil
|
||||
}
|
||||
|
||||
// GetMVNOByBusinessID retrieves an MVNO by business ID
|
||||
func (r *GormRepository) GetMVNOByBusinessID(ctx context.Context, businessID string) (*mvno.MVNO, error) {
|
||||
var mvno mvno.MVNO
|
||||
if err := r.db.WithContext(ctx).Where("business_id = ?", businessID).First(&mvno).Error; err != nil {
|
||||
if err == gorm.ErrRecordNotFound {
|
||||
return nil, fmt.Errorf("MVNO not found for business ID: %s", businessID)
|
||||
}
|
||||
return nil, fmt.Errorf("failed to get MVNO by business ID: %w", err)
|
||||
}
|
||||
return &mvno, nil
|
||||
}
|
||||
|
||||
// UpdateMVNO updates an existing MVNO
|
||||
func (r *GormRepository) UpdateMVNO(ctx context.Context, mvno *mvno.MVNO) error {
|
||||
if err := r.db.WithContext(ctx).Save(mvno).Error; err != nil {
|
||||
return fmt.Errorf("failed to update MVNO: %w", err)
|
||||
}
|
||||
|
||||
r.logger.Info("MVNO updated", "id", mvno.ID, "status", mvno.Status)
|
||||
return nil
|
||||
}
|
||||
|
||||
// ListMVNOs lists MVNOs with optional filtering
|
||||
func (r *GormRepository) ListMVNOs(ctx context.Context, filter *mvno.MVNOFilter) ([]*mvno.MVNO, error) {
|
||||
query := r.db.WithContext(ctx).Model(&mvno.MVNO{})
|
||||
|
||||
// Apply filters
|
||||
if filter != nil {
|
||||
if filter.Status != "" {
|
||||
query = query.Where("status = ?", filter.Status)
|
||||
}
|
||||
if filter.Plan != "" {
|
||||
query = query.Where("plan = ?", filter.Plan)
|
||||
}
|
||||
if filter.BusinessID != "" {
|
||||
query = query.Where("business_id = ?", filter.BusinessID)
|
||||
}
|
||||
if filter.CreatedAfter != nil {
|
||||
query = query.Where("created_at >= ?", *filter.CreatedAfter)
|
||||
}
|
||||
if filter.CreatedBefore != nil {
|
||||
query = query.Where("created_at <= ?", *filter.CreatedBefore)
|
||||
}
|
||||
if filter.Limit > 0 {
|
||||
query = query.Limit(filter.Limit)
|
||||
}
|
||||
if filter.Offset > 0 {
|
||||
query = query.Offset(filter.Offset)
|
||||
}
|
||||
}
|
||||
|
||||
var mvnos []*mvno.MVNO
|
||||
if err := query.Order("created_at DESC").Find(&mvnos).Error; err != nil {
|
||||
return nil, fmt.Errorf("failed to list MVNOs: %w", err)
|
||||
}
|
||||
|
||||
return mvnos, nil
|
||||
}
|
||||
|
||||
// DeleteMVNO soft deletes an MVNO
|
||||
func (r *GormRepository) DeleteMVNO(ctx context.Context, id string) error {
|
||||
if err := r.db.WithContext(ctx).Where("id = ?", id).Delete(&mvno.MVNO{}).Error; err != nil {
|
||||
return fmt.Errorf("failed to delete MVNO: %w", err)
|
||||
}
|
||||
|
||||
r.logger.Info("MVNO deleted", "id", id)
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetMVNOStats returns statistics about MVNOs
|
||||
func (r *GormRepository) GetMVNOStats(ctx context.Context) (map[string]any, error) {
|
||||
stats := make(map[string]any)
|
||||
|
||||
// Total count
|
||||
var totalCount int64
|
||||
if err := r.db.WithContext(ctx).Model(&mvno.MVNO{}).Count(&totalCount).Error; err != nil {
|
||||
return nil, fmt.Errorf("failed to count total MVNOs: %w", err)
|
||||
}
|
||||
stats["total"] = totalCount
|
||||
|
||||
// Count by status
|
||||
var statusCounts []struct {
|
||||
Status mvno.MVNOStatus `gorm:"column:status"`
|
||||
Count int64 `gorm:"column:count"`
|
||||
}
|
||||
if err := r.db.WithContext(ctx).Model(&mvno.MVNO{}).
|
||||
Select("status, COUNT(*) as count").
|
||||
Group("status").
|
||||
Scan(&statusCounts).Error; err != nil {
|
||||
return nil, fmt.Errorf("failed to count by status: %w", err)
|
||||
}
|
||||
|
||||
statusMap := make(map[string]int64)
|
||||
for _, sc := range statusCounts {
|
||||
statusMap[string(sc.Status)] = sc.Count
|
||||
}
|
||||
stats["by_status"] = statusMap
|
||||
|
||||
// Count by plan
|
||||
var planCounts []struct {
|
||||
Plan mvno.MVNOPlan `gorm:"column:plan"`
|
||||
Count int64 `gorm:"column:count"`
|
||||
}
|
||||
if err := r.db.WithContext(ctx).Model(&mvno.MVNO{}).
|
||||
Select("plan, COUNT(*) as count").
|
||||
Group("plan").
|
||||
Scan(&planCounts).Error; err != nil {
|
||||
return nil, fmt.Errorf("failed to count by plan: %w", err)
|
||||
}
|
||||
|
||||
planMap := make(map[string]int64)
|
||||
for _, pc := range planCounts {
|
||||
planMap[string(pc.Plan)] = pc.Count
|
||||
}
|
||||
stats["by_plan"] = planMap
|
||||
|
||||
return stats, nil
|
||||
}
|
||||
|
||||
// UpdateMVNOStatus updates only the status of an MVNO
|
||||
func (r *GormRepository) UpdateMVNOStatus(ctx context.Context, id string, status mvno.MVNOStatus) error {
|
||||
if err := r.db.WithContext(ctx).Model(&mvno.MVNO{}).Where("id = ?", id).Update("status", status).Error; err != nil {
|
||||
return fmt.Errorf("failed to update MVNO status: %w", err)
|
||||
}
|
||||
|
||||
r.logger.Info("MVNO status updated", "id", id, "new_status", status)
|
||||
return nil
|
||||
}
|
||||
Reference in New Issue
Block a user