@@ -3,6 +3,7 @@ package repository
33import (
44 "context"
55 "database/sql"
6+ "database/sql/driver"
67 "fmt"
78 "reflect"
89 "testing"
@@ -21,20 +22,21 @@ func TestUsageLogRepositoryCreateSyncRequestTypeAndLegacyFields(t *testing.T) {
2122
2223 createdAt := time .Date (2025 , 1 , 1 , 12 , 0 , 0 , 0 , time .UTC )
2324 log := & service.UsageLog {
24- UserID : 1 ,
25- APIKeyID : 2 ,
26- AccountID : 3 ,
27- RequestID : "req-1" ,
28- Model : "gpt-5" ,
29- InputTokens : 10 ,
30- OutputTokens : 20 ,
31- TotalCost : 1 ,
32- ActualCost : 1 ,
33- BillingType : service .BillingTypeBalance ,
34- RequestType : service .RequestTypeWSV2 ,
35- Stream : false ,
36- OpenAIWSMode : false ,
37- CreatedAt : createdAt ,
25+ UserID : 1 ,
26+ APIKeyID : 2 ,
27+ AccountID : 3 ,
28+ RequestID : "req-1" ,
29+ Model : "gpt-5" ,
30+ RequestedModel : "gpt-5" ,
31+ InputTokens : 10 ,
32+ OutputTokens : 20 ,
33+ TotalCost : 1 ,
34+ ActualCost : 1 ,
35+ BillingType : service .BillingTypeBalance ,
36+ RequestType : service .RequestTypeWSV2 ,
37+ Stream : false ,
38+ OpenAIWSMode : false ,
39+ CreatedAt : createdAt ,
3840 }
3941
4042 mock .ExpectQuery ("INSERT INTO usage_logs" ).
@@ -44,6 +46,7 @@ func TestUsageLogRepositoryCreateSyncRequestTypeAndLegacyFields(t *testing.T) {
4446 log .AccountID ,
4547 log .RequestID ,
4648 log .Model ,
49+ log .RequestedModel ,
4750 sqlmock .AnyArg (), // upstream_model
4851 sqlmock .AnyArg (), // group_id
4952 sqlmock .AnyArg (), // subscription_id
@@ -99,13 +102,14 @@ func TestUsageLogRepositoryCreate_PersistsServiceTier(t *testing.T) {
99102 createdAt := time .Date (2025 , 1 , 2 , 12 , 0 , 0 , 0 , time .UTC )
100103 serviceTier := "priority"
101104 log := & service.UsageLog {
102- UserID : 1 ,
103- APIKeyID : 2 ,
104- AccountID : 3 ,
105- RequestID : "req-service-tier" ,
106- Model : "gpt-5.4" ,
107- ServiceTier : & serviceTier ,
108- CreatedAt : createdAt ,
105+ UserID : 1 ,
106+ APIKeyID : 2 ,
107+ AccountID : 3 ,
108+ RequestID : "req-service-tier" ,
109+ Model : "gpt-5.4" ,
110+ RequestedModel : "gpt-5.4" ,
111+ ServiceTier : & serviceTier ,
112+ CreatedAt : createdAt ,
109113 }
110114
111115 mock .ExpectQuery ("INSERT INTO usage_logs" ).
@@ -115,6 +119,7 @@ func TestUsageLogRepositoryCreate_PersistsServiceTier(t *testing.T) {
115119 log .AccountID ,
116120 log .RequestID ,
117121 log .Model ,
122+ log .RequestedModel ,
118123 sqlmock .AnyArg (),
119124 sqlmock .AnyArg (),
120125 sqlmock .AnyArg (),
@@ -158,6 +163,75 @@ func TestUsageLogRepositoryCreate_PersistsServiceTier(t *testing.T) {
158163 require .NoError (t , mock .ExpectationsWereMet ())
159164}
160165
166+ func TestBuildUsageLogBestEffortInsertQuery_IncludesRequestedModelColumn (t * testing.T ) {
167+ prepared := prepareUsageLogInsert (& service.UsageLog {
168+ UserID : 1 ,
169+ APIKeyID : 2 ,
170+ AccountID : 3 ,
171+ RequestID : "req-best-effort-query" ,
172+ Model : "gpt-5" ,
173+ RequestedModel : "gpt-5" ,
174+ CreatedAt : time .Date (2025 , 1 , 3 , 12 , 0 , 0 , 0 , time .UTC ),
175+ })
176+
177+ query , args := buildUsageLogBestEffortInsertQuery ([]usageLogInsertPrepared {prepared })
178+
179+ require .Contains (t , query , "INSERT INTO usage_logs (" )
180+ require .Contains (t , query , "\n \t \t \t model,\n \t \t \t requested_model,\n \t \t \t upstream_model," )
181+ require .Contains (t , query , "\n \t \t \t request_id,\n \t \t \t model,\n \t \t \t requested_model,\n \t \t \t upstream_model," )
182+ require .Len (t , args , len (prepared .args ))
183+ require .Equal (t , prepared .args [5 ], args [5 ])
184+ }
185+
186+ func TestExecUsageLogInsertNoResult_PersistsRequestedModel (t * testing.T ) {
187+ db , mock := newSQLMock (t )
188+ prepared := prepareUsageLogInsert (& service.UsageLog {
189+ UserID : 1 ,
190+ APIKeyID : 2 ,
191+ AccountID : 3 ,
192+ RequestID : "req-best-effort-exec" ,
193+ Model : "gpt-5" ,
194+ RequestedModel : "gpt-5" ,
195+ CreatedAt : time .Date (2025 , 1 , 4 , 12 , 0 , 0 , 0 , time .UTC ),
196+ })
197+
198+ mock .ExpectExec ("INSERT INTO usage_logs" ).
199+ WithArgs (anySliceToDriverValues (prepared .args )... ).
200+ WillReturnResult (sqlmock .NewResult (0 , 1 ))
201+
202+ err := execUsageLogInsertNoResult (context .Background (), db , prepared )
203+ require .NoError (t , err )
204+ require .NoError (t , mock .ExpectationsWereMet ())
205+ }
206+
207+ func TestPrepareUsageLogInsert_ArgCountMatchesTypes (t * testing.T ) {
208+ prepared := prepareUsageLogInsert (& service.UsageLog {
209+ UserID : 1 ,
210+ APIKeyID : 2 ,
211+ AccountID : 3 ,
212+ RequestID : "req-arg-count" ,
213+ Model : "gpt-5" ,
214+ RequestedModel : "gpt-5" ,
215+ CreatedAt : time .Date (2025 , 1 , 5 , 12 , 0 , 0 , 0 , time .UTC ),
216+ })
217+
218+ require .Len (t , prepared .args , len (usageLogInsertArgTypes ))
219+ }
220+
221+ func TestCoalesceTrimmedString (t * testing.T ) {
222+ require .Equal (t , "fallback" , coalesceTrimmedString (sql.NullString {}, "fallback" ))
223+ require .Equal (t , "fallback" , coalesceTrimmedString (sql.NullString {Valid : true , String : " " }, "fallback" ))
224+ require .Equal (t , "value" , coalesceTrimmedString (sql.NullString {Valid : true , String : "value" }, "fallback" ))
225+ }
226+
227+ func anySliceToDriverValues (values []any ) []driver.Value {
228+ out := make ([]driver.Value , 0 , len (values ))
229+ for _ , value := range values {
230+ out = append (out , value )
231+ }
232+ return out
233+ }
234+
161235func TestUsageLogRepositoryListWithFiltersRequestTypePriority (t * testing.T ) {
162236 db , mock := newSQLMock (t )
163237 repo := & usageLogRepository {sql : db }
@@ -354,7 +428,8 @@ func TestScanUsageLogRequestTypeAndLegacyFallback(t *testing.T) {
354428 int64 (20 ), // api_key_id
355429 int64 (30 ), // account_id
356430 sql.NullString {Valid : true , String : "req-1" },
357- "gpt-5" , // model
431+ "gpt-5" , // model
432+ sql.NullString {Valid : true , String : "gpt-5" }, // requested_model
358433 sql.NullString {}, // upstream_model
359434 sql.NullInt64 {}, // group_id
360435 sql.NullInt64 {}, // subscription_id
@@ -407,6 +482,7 @@ func TestScanUsageLogRequestTypeAndLegacyFallback(t *testing.T) {
407482 int64 (31 ),
408483 sql.NullString {Valid : true , String : "req-2" },
409484 "gpt-5" ,
485+ sql.NullString {Valid : true , String : "gpt-5" },
410486 sql.NullString {},
411487 sql.NullInt64 {},
412488 sql.NullInt64 {},
@@ -449,6 +525,7 @@ func TestScanUsageLogRequestTypeAndLegacyFallback(t *testing.T) {
449525 int64 (32 ),
450526 sql.NullString {Valid : true , String : "req-3" },
451527 "gpt-5.4" ,
528+ sql.NullString {Valid : true , String : "gpt-5.4" },
452529 sql.NullString {},
453530 sql.NullInt64 {},
454531 sql.NullInt64 {},
0 commit comments