group_detail_stats_database_test.go 3.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162
  1. //go:build protectionintegration
  2. package repository
  3. import (
  4. "context"
  5. "testing"
  6. "time"
  7. "github.com/Wei-Shaw/sub2api/internal/service"
  8. "github.com/stretchr/testify/require"
  9. )
  10. func TestGroupDetailStatsHistoricalCostsAndCurrentBindings(t *testing.T) {
  11. client, db := protectionTestDatabase(t)
  12. for i, name := range []string{"Stats group", "Other"} {
  13. group, err := client.Group.Create().SetName(name).SetPlatform("openai").SetStatus("active").Save(context.Background())
  14. require.NoError(t, err)
  15. _, err = db.Exec(`UPDATE groups SET id=$1 WHERE id=$2`, 900+i, group.ID)
  16. require.NoError(t, err)
  17. }
  18. _, err := db.Exec(`CREATE TABLE api_keys(id BIGINT PRIMARY KEY,group_id BIGINT,status TEXT,expires_at TIMESTAMPTZ,deleted_at TIMESTAMPTZ);
  19. INSERT INTO api_keys VALUES(1,900,'active',NULL,NULL),(2,900,'active',NOW()-INTERVAL '1 day',NULL),(3,900,'disabled',NULL,NULL),(4,900,'active',NULL,NOW()),(5,901,'active',NULL,NULL);
  20. CREATE TABLE usage_logs(id BIGINT PRIMARY KEY,group_id BIGINT,input_tokens INT,output_tokens INT,cache_creation_tokens INT,cache_read_tokens INT,total_cost NUMERIC,actual_cost NUMERIC,account_stats_cost NUMERIC,account_rate_multiplier NUMERIC,billing_type INT,duration_ms INT,created_at TIMESTAMPTZ);
  21. INSERT INTO usage_logs VALUES
  22. (1,900,10,20,0,5,10,12,NULL,0.5,0,1000,'2026-09-10T00:00:00Z'),
  23. (2,900,1,2,3,4,20,4,3,2,1,3000,'2026-09-11T00:00:00Z'),
  24. (3,900,2,2,0,0,2,0,NULL,NULL,0,2000,'2026-09-12T00:00:00Z'),
  25. (4,901,99,99,0,0,999,999,999,1,0,9999,'2026-09-10T00:00:00Z');`)
  26. require.NoError(t, err)
  27. repo := &usageLogRepository{sql: db}
  28. stats, err := repo.GetGroupDetailStats(context.Background(), 900, nil, nil)
  29. require.NoError(t, err)
  30. require.EqualValues(t, 3, stats.TotalAPIKeys)
  31. require.EqualValues(t, 1, stats.ActiveAPIKeys)
  32. require.EqualValues(t, 3, stats.TotalRequests)
  33. require.EqualValues(t, 49, stats.TotalTokens)
  34. require.Equal(t, 32.0, stats.TotalCost)
  35. require.Equal(t, 16.0, stats.TotalActualCost)
  36. require.Equal(t, 13.0, stats.TotalAccountCost)
  37. require.Equal(t, 12.0, stats.BalanceCost)
  38. require.Equal(t, 4.0, stats.SubscriptionCost)
  39. require.EqualValues(t, 1, stats.ZeroChargeRequests)
  40. require.Equal(t, 2000.0, stats.AverageDurationMS)
  41. // Moving/deleting a key cannot move the original usage out of its historical group.
  42. _, err = db.Exec(`UPDATE api_keys SET group_id=901 WHERE id=1`)
  43. require.NoError(t, err)
  44. from := time.Date(2026, 9, 11, 0, 0, 0, 0, time.UTC)
  45. to := from.AddDate(0, 0, 1)
  46. stats, err = repo.GetGroupDetailStats(context.Background(), 900, &from, &to)
  47. require.NoError(t, err)
  48. require.EqualValues(t, 1, stats.TotalRequests)
  49. require.Equal(t, 20.0, stats.TotalCost)
  50. require.Equal(t, 6.0, stats.TotalAccountCost)
  51. require.EqualValues(t, 2, stats.TotalAPIKeys)
  52. _, err = repo.GetGroupDetailStats(context.Background(), 999, nil, nil)
  53. require.ErrorIs(t, err, service.ErrGroupNotFound)
  54. stats, err = repo.GetGroupDetailStats(context.Background(), 901, &to, nil)
  55. require.NoError(t, err)
  56. require.Zero(t, stats.TotalRequests)
  57. require.Zero(t, stats.TotalCost)
  58. }