fix: prevent silent data truncation in report generators (#257)
* fix: prevent silent data truncation in report generators Supabase PostgREST silently truncates queries at 1000 rows. Several report generators used bare .select() without fetchAllRows(), causing incomplete financial data — a BFL compliance violation. Wrapped 10 queries across 7 files with fetchAllRows(): - monthly-breakdown: journal_entry_lines (easily >1000/period) - ar-ledger: unpaid invoices - supplier-ledger: unpaid supplier invoices - salary-journal: salary_run_employees (+ optimized with !inner join) - vacation-liability: employees + salary_run_employees - full-archive-export: document_attachments + journal_entry IDs - ingest.ts: supplier invoices for auto-matching Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: address Greptile review — try/catch and client-side safety checks - Wrap full-archive-export document fetch in try/catch to match the VAT section pattern — a failed document query should not prevent the rest of the archive from being generated. - Restore client-side year/status safety checks in salary-journal and vacation-liability as defense-in-depth against PostgREST !inner filter regressions, per BFL lönejournal and BFNAR 2016:10 compliance. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.6
parent
4fbfadb2b7
commit
fe137346df
@@ -7,6 +7,7 @@ import { findSupplierInvoiceMatch } from '@/lib/invoices/supplier-invoice-matchi
|
||||
import { tryReconcileTransaction, fetchUnlinkedGLLines } from '@/lib/reconciliation/bank-reconciliation'
|
||||
import { fetchMultipleRates } from '@/lib/currency/riksbanken'
|
||||
import { logMatchEvent } from '@/lib/invoices/match-log'
|
||||
import { fetchAllRows } from '@/lib/supabase/fetch-all'
|
||||
import type { UnlinkedGLLine } from '@/lib/reconciliation/bank-reconciliation'
|
||||
import type { Transaction, RawTransaction, IngestResult, IngestOptions, SupplierInvoice, Currency, ExchangeRate } from '@/types'
|
||||
|
||||
@@ -135,14 +136,15 @@ export async function ingestTransactions(
|
||||
|
||||
// Pre-fetch unpaid supplier invoices for expense matching (non-critical)
|
||||
try {
|
||||
const { data } = await supabase
|
||||
.from('supplier_invoices')
|
||||
.select('*, supplier:suppliers(*)')
|
||||
.eq('company_id', companyId)
|
||||
.in('status', ['registered', 'approved'])
|
||||
.gt('remaining_amount', 0)
|
||||
|
||||
if (data) unpaidSupplierInvoices = data as SupplierInvoice[]
|
||||
unpaidSupplierInvoices = await fetchAllRows<SupplierInvoice>(({ from, to }) =>
|
||||
supabase
|
||||
.from('supplier_invoices')
|
||||
.select('*, supplier:suppliers(*)')
|
||||
.eq('company_id', companyId)
|
||||
.in('status', ['registered', 'approved'])
|
||||
.gt('remaining_amount', 0)
|
||||
.range(from, to)
|
||||
)
|
||||
} catch {
|
||||
// Non-critical — supplier invoice matching will be skipped
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user