diff --git a/frontend/src/components/admin/usage/UsageTable.vue b/frontend/src/components/admin/usage/UsageTable.vue index 3b2509129b..364a3072e6 100644 --- a/frontend/src/components/admin/usage/UsageTable.vue +++ b/frontend/src/components/admin/usage/UsageTable.vue @@ -410,19 +410,19 @@
{{ t('usage.costDetails') }}
{{ t('admin.usage.inputCost') }} - ${{ tooltipData.input_cost.toFixed(6) }} + ${{ tooltipData.input_cost.toFixed(8) }}
{{ t('usage.imageInputCost') }} - ${{ tooltipData.image_input_cost.toFixed(6) }} + ${{ tooltipData.image_input_cost.toFixed(8) }}
{{ t('admin.usage.outputCost') }} - ${{ tooltipData.output_cost.toFixed(6) }} + ${{ tooltipData.output_cost.toFixed(8) }}
{{ t('usage.imageOutputCost') }} - ${{ tooltipData.image_output_cost.toFixed(6) }} + ${{ tooltipData.image_output_cost.toFixed(8) }}
{{ t('usage.unitPrice') }} - ${{ tooltipData?.total_cost?.toFixed(6) || '0.000000' }} + ${{ tooltipData?.total_cost?.toFixed(8) || '0.00000000' }}
{{ t('admin.usage.cacheCreationCost') }} - ${{ tooltipData.cache_creation_cost.toFixed(6) }} + ${{ tooltipData.cache_creation_cost.toFixed(8) }}
{{ t('admin.usage.cacheReadCost') }} - ${{ tooltipData.cache_read_cost.toFixed(6) }} + ${{ tooltipData.cache_read_cost.toFixed(8) }}
@@ -501,11 +501,11 @@
{{ t('usage.original') }} - ${{ tooltipData?.total_cost?.toFixed(6) || '0.000000' }} + ${{ tooltipData?.total_cost?.toFixed(8) || '0.00000000' }}
{{ t('usage.userBilled') }} - ${{ tooltipData?.actual_cost?.toFixed(6) || '0.000000' }} + ${{ tooltipData?.actual_cost?.toFixed(8) || '0.00000000' }}
diff --git a/frontend/src/components/admin/usage/__tests__/UsageTable.spec.ts b/frontend/src/components/admin/usage/__tests__/UsageTable.spec.ts index 3262fa0408..d915fa4c42 100644 --- a/frontend/src/components/admin/usage/__tests__/UsageTable.spec.ts +++ b/frontend/src/components/admin/usage/__tests__/UsageTable.spec.ts @@ -275,6 +275,53 @@ describe('admin UsageTable tooltip', () => { expect(text).toContain('$0.069568') }) + it.each(['token', 'image', 'per_request'])('keeps eight decimal places in %s cost details', async (billingMode) => { + const row = { + ...baseImageRow, + billing_mode: billingMode, + image_count: billingMode === 'image' ? 2 : 0, + input_cost: 0.00000001, + image_input_cost: 0.00000002, + output_cost: 0.00000003, + image_output_cost: 0.00000004, + cache_creation_cost: 0.00000005, + cache_read_cost: 0.00000006, + total_cost: 0.00000022, + actual_cost: 0.00000042, + account_stats_cost: 0.00000012, + account_rate_multiplier: 1.5, + } + const wrapper = mount(UsageTable, { + props: { data: [row], loading: false, columns: [] }, + global: { stubs: { DataTable: DataTableStub, EmptyState: true, Icon: true, Teleport: true } }, + }) + const triggers = wrapper.findAll('.group.relative') + await triggers[triggers.length - 1].trigger('mouseenter') + const amounts = wrapper.get('.fixed').findAll('span').map(span => span.text()) + expect(amounts).toEqual(expect.arrayContaining([ + '$0.00000001', '$0.00000002', '$0.00000003', '$0.00000004', + '$0.00000005', '$0.00000006', '$0.00000022', '$0.00000042', '$0.00000018', + ])) + if (billingMode === 'image') expect(amounts).toContain('$0.00000011') + wrapper.unmount() + }) + + it('uses eight decimal places for missing cost values', async () => { + const wrapper = mount(UsageTable, { + props: { + data: [{ ...baseImageRow, billing_mode: 'per_request', image_count: 0, total_cost: undefined, actual_cost: undefined }], + loading: false, + columns: [], + }, + global: { stubs: { DataTable: DataTableStub, EmptyState: true, Icon: true, Teleport: true } }, + }) + const triggers = wrapper.findAll('.group.relative') + await triggers[triggers.length - 1].trigger('mouseenter') + const amounts = wrapper.get('.fixed').findAll('span').map(span => span.text()).filter(text => text.startsWith('$')) + expect(amounts).toEqual(['$0.00000000', '$0.00000000', '$0.00000000', '$0.00000000']) + wrapper.unmount() + }) + it('shows requested and upstream models separately for admin rows', () => { const row = { request_id: 'req-admin-model-1',