Bug/gh issues fiz (#1103)
* refactor: optimize page loading and data fetching * fix: resolve recurring production runtime errors * feat: add MCP company and customer updates * fix: handle year-end tax adjustments * feat: harden annual report compliance * fix: expand invoice logo and font support * fix: sanitize API route error responses * fix: sanitize user-facing error messages * feat: persist onboarding and tax assessment notices * fix: reduce cloud backup audit churn * feat: refine invoice editor layout * fix: show saved tax adjustments in INK2 * fix: complete annual report API mappings * docs: record operational safeguards and decisions * fix: harden annual report review findings * fix: adjust column span for description based on VAT registration * New css class name
This commit is contained in:
@@ -0,0 +1,43 @@
|
||||
import { describe, expect, it, vi } from 'vitest'
|
||||
import { getAuditLog } from '../audit-service'
|
||||
|
||||
function createQuery(result: { data: unknown[]; error: unknown; count: number | null }) {
|
||||
const query = {
|
||||
select: vi.fn(),
|
||||
eq: vi.fn(),
|
||||
order: vi.fn(),
|
||||
range: vi.fn(),
|
||||
}
|
||||
query.select.mockReturnValue(query)
|
||||
query.eq.mockReturnValue(query)
|
||||
query.order.mockReturnValue(query)
|
||||
query.range.mockResolvedValue(result)
|
||||
return query
|
||||
}
|
||||
|
||||
describe('getAuditLog', () => {
|
||||
it('requests an exact count for interactive pagination', async () => {
|
||||
const query = createQuery({ data: [], error: null, count: 12 })
|
||||
const supabase = { from: vi.fn(() => query) }
|
||||
|
||||
const result = await getAuditLog(supabase as never, 'company-1')
|
||||
|
||||
expect(query.select).toHaveBeenCalledWith('*', { count: 'exact' })
|
||||
expect(result.count).toBe(12)
|
||||
})
|
||||
|
||||
it('skips the exact count for full archive exports', async () => {
|
||||
const query = createQuery({ data: [], error: null, count: null })
|
||||
const supabase = { from: vi.fn(() => query) }
|
||||
|
||||
const result = await getAuditLog(supabase as never, 'company-1', {
|
||||
includeCount: false,
|
||||
pageSize: 500,
|
||||
})
|
||||
|
||||
expect(query.select).toHaveBeenCalledWith('*')
|
||||
expect(query.order).toHaveBeenNthCalledWith(1, 'created_at', { ascending: false })
|
||||
expect(query.order).toHaveBeenNthCalledWith(2, 'id', { ascending: false })
|
||||
expect(result.count).toBe(0)
|
||||
})
|
||||
})
|
||||
@@ -16,6 +16,8 @@ export interface AuditLogFilters {
|
||||
to_date?: string
|
||||
page?: number
|
||||
pageSize?: number
|
||||
/** Full exports can skip the expensive exact count and stop on a short page. */
|
||||
includeCount?: boolean
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -28,13 +30,16 @@ export async function getAuditLog(
|
||||
): Promise<{ data: AuditLogEntry[]; count: number }> {
|
||||
const page = filters.page ?? 1
|
||||
const pageSize = filters.pageSize ?? 50
|
||||
const includeCount = filters.includeCount ?? true
|
||||
const offset = (page - 1) * pageSize
|
||||
|
||||
let query = supabase
|
||||
.from('audit_log')
|
||||
.select('*', { count: 'exact' })
|
||||
const auditTable = supabase.from('audit_log')
|
||||
let query = (includeCount
|
||||
? auditTable.select('*', { count: 'exact' })
|
||||
: auditTable.select('*'))
|
||||
.eq('company_id', companyId)
|
||||
.order('created_at', { ascending: false })
|
||||
.order('id', { ascending: false })
|
||||
.range(offset, offset + pageSize - 1)
|
||||
|
||||
if (filters.action) {
|
||||
@@ -61,7 +66,7 @@ export async function getAuditLog(
|
||||
|
||||
return {
|
||||
data: (data as AuditLogEntry[]) || [],
|
||||
count: count ?? 0,
|
||||
count: includeCount ? count ?? 0 : 0,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user