diff --git a/backend/internal/service/openai_gateway_record_usage_test.go b/backend/internal/service/openai_gateway_record_usage_test.go index b7682cb400..be4cf1850c 100644 --- a/backend/internal/service/openai_gateway_record_usage_test.go +++ b/backend/internal/service/openai_gateway_record_usage_test.go @@ -3210,6 +3210,51 @@ func TestOpenAIGatewayServiceRecordUsage_FreeOpenAIFastChargesStandard(t *testin require.InDelta(t, standardTotal*0.5, usageRepo.lastLog.ActualCost, 1e-10) } +func TestOpenAIGatewayServiceRecordUsage_FreeOpenAIFastMissingPricingRecordsZeroCostUsageLog(t *testing.T) { + usageRepo := &openAIRecordUsageLogRepoStub{inserted: true} + svc := newOpenAIRecordUsageServiceForTest( + usageRepo, + &openAIRecordUsageUserRepoStub{}, + &openAIRecordUsageSubRepoStub{}, + nil, + ) + svc.resolver = NewModelPricingResolver(nil, svc.billingService) + groupID := int64(78) + serviceTier := "priority" + apiKey := &APIKey{ + ID: 1021, + GroupID: &groupID, + Group: &Group{ + ID: groupID, Platform: PlatformOpenAI, Status: StatusActive, + Hydrated: true, RateMultiplier: 1, FreeOpenAIFast: true, + }, + } + + err := svc.RecordUsage(context.Background(), &OpenAIRecordUsageInput{ + Result: &OpenAIForwardResult{ + RequestID: "resp_free_fast_missing_pricing", + ServiceTier: &serviceTier, + Usage: OpenAIUsage{InputTokens: 1200, OutputTokens: 300}, + Model: "pricing-missing-test-model", + Duration: time.Second, + }, + APIKey: apiKey, + User: &User{ID: 2021}, + Account: &Account{ID: 3021, Platform: PlatformOpenAI, Type: AccountTypeAPIKey}, + }) + + require.NoError(t, err) + require.Equal(t, 1, usageRepo.calls) + require.NotNil(t, usageRepo.lastLog) + require.Equal(t, "resp_free_fast_missing_pricing", usageRepo.lastLog.RequestID) + require.Equal(t, 1200, usageRepo.lastLog.InputTokens) + require.Equal(t, 300, usageRepo.lastLog.OutputTokens) + require.NotNil(t, usageRepo.lastLog.ServiceTier) + require.Equal(t, "priority", *usageRepo.lastLog.ServiceTier) + require.Zero(t, usageRepo.lastLog.TotalCost) + require.Zero(t, usageRepo.lastLog.ActualCost) +} + func TestGroupBillsOpenAIFastAtStandardRequiresOpenAIAccount(t *testing.T) { apiKey := &APIKey{Group: &Group{Platform: PlatformComposite, FreeOpenAIFast: true}} diff --git a/backend/internal/service/openai_gateway_usage.go b/backend/internal/service/openai_gateway_usage.go index cd2c7aadea..f42d81b488 100644 --- a/backend/internal/service/openai_gateway_usage.go +++ b/backend/internal/service/openai_gateway_usage.go @@ -314,10 +314,12 @@ func (s *OpenAIGatewayService) RecordUsage(ctx context.Context, input *OpenAIRec longContextBillingGate, pricingAt, ) - if standardErr != nil { + if standardErr != nil && !isUsagePricingUnavailableError(standardErr) { return standardErr } - if cost != nil && standardCost != nil { + // Missing pricing already fell back to a zero-cost log above; keep that + // usage row instead of dropping it on the Standard re-evaluation. + if standardErr == nil && cost != nil && standardCost != nil { cost.ActualCost = standardCost.ActualCost } }