refactor: consolidate lib/invoice/ into lib/invoices/
Merge the singular lib/invoice/ directory into the plural lib/invoices/ to align with the codebase convention (transactions/, extensions/, reports/, etc.). Updates all import paths and CLAUDE.md architecture docs. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -74,8 +74,7 @@ lib/
|
||||
events/ Event bus (bus.ts, types.ts)
|
||||
extensions/ Extension registry, loader, types
|
||||
import/ SIE and bank file parser
|
||||
invoice/ VAT rules for invoicing
|
||||
invoices/ Invoice business logic helpers
|
||||
invoices/ Invoice helpers (VAT rules, PDF template, matching, reminders)
|
||||
reports/ Financial reports (trial-balance, income-statement,
|
||||
balance-sheet, vat-declaration, sie-export,
|
||||
supplier-ledger, supplier-reconciliation,
|
||||
@@ -266,7 +265,7 @@ All defined in `lib/events/types.ts`:
|
||||
|
||||
### Scope
|
||||
|
||||
Only test business logic in `lib/`. No component tests, no API route tests, no E2E tests.
|
||||
Test business logic in `lib/` and API routes in `app/api/`. No component tests, no E2E tests.
|
||||
|
||||
### Framework
|
||||
|
||||
@@ -302,6 +301,14 @@ mockResult({ data: makeTransaction(), error: null })
|
||||
- Test error paths (missing fiscal period, unbalanced entries)
|
||||
- Verify events are emitted correctly
|
||||
|
||||
### API Route Tests
|
||||
|
||||
- Colocated `__tests__/` directories alongside route files (e.g., `app/api/invoices/__tests__/route.test.ts`)
|
||||
- Mock `@/lib/supabase/server`, `@/lib/init`, and lib functions — do NOT re-test lib business logic
|
||||
- Use `createMockRequest()`, `parseJsonResponse()`, `createMockRouteParams()` from `tests/helpers.ts`
|
||||
- Use `createQueuedMockSupabase()` for routes with multiple sequential Supabase calls
|
||||
- Test: auth (401), validation (400), not found (404), errors (500), happy path, non-blocking journal entry failures
|
||||
|
||||
### Reference Tests
|
||||
|
||||
- `lib/bookkeeping/__tests__/engine.test.ts` — Balance validation
|
||||
|
||||
@@ -10,7 +10,7 @@ import { Label } from '@/components/ui/label'
|
||||
import { Separator } from '@/components/ui/separator'
|
||||
import { useToast } from '@/components/ui/use-toast'
|
||||
import { formatCurrency, formatDate } from '@/lib/utils'
|
||||
import { getVatTreatmentLabel } from '@/lib/invoice/vat-rules'
|
||||
import { getVatTreatmentLabel } from '@/lib/invoices/vat-rules'
|
||||
import { Loader2, ArrowLeft, AlertTriangle } from 'lucide-react'
|
||||
import type { Invoice, InvoiceItem, Customer } from '@/types'
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ import { Badge } from '@/components/ui/badge'
|
||||
import { Separator } from '@/components/ui/separator'
|
||||
import { useToast } from '@/components/ui/use-toast'
|
||||
import { formatCurrency, formatDate } from '@/lib/utils'
|
||||
import { getVatTreatmentLabel } from '@/lib/invoice/vat-rules'
|
||||
import { getVatTreatmentLabel } from '@/lib/invoices/vat-rules'
|
||||
import {
|
||||
Loader2,
|
||||
ArrowLeft,
|
||||
|
||||
@@ -16,7 +16,7 @@ import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@
|
||||
import { Separator } from '@/components/ui/separator'
|
||||
import { useToast } from '@/components/ui/use-toast'
|
||||
import { formatCurrency } from '@/lib/utils'
|
||||
import { getVatRules, getVatTreatmentLabel } from '@/lib/invoice/vat-rules'
|
||||
import { getVatRules, getVatTreatmentLabel } from '@/lib/invoices/vat-rules'
|
||||
import { Loader2, Plus, Trash2, ArrowLeft } from 'lucide-react'
|
||||
import { ConfirmationDialog } from '@/components/ui/confirmation-dialog'
|
||||
import { InvoiceReviewContent } from '@/components/invoices/InvoiceReviewContent'
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { createClient } from '@/lib/supabase/server'
|
||||
import { NextResponse } from 'next/server'
|
||||
import { renderToBuffer } from '@react-pdf/renderer'
|
||||
import { InvoicePDF } from '@/lib/invoice/pdf-template'
|
||||
import { InvoicePDF } from '@/lib/invoices/pdf-template'
|
||||
import type { Invoice, InvoiceItem, Customer, CompanySettings } from '@/types'
|
||||
|
||||
export async function GET(
|
||||
|
||||
@@ -3,7 +3,7 @@ import { NextResponse } from 'next/server'
|
||||
import { eventBus } from '@/lib/events'
|
||||
import { ensureInitialized } from '@/lib/init'
|
||||
import { renderToBuffer } from '@react-pdf/renderer'
|
||||
import { InvoicePDF } from '@/lib/invoice/pdf-template'
|
||||
import { InvoicePDF } from '@/lib/invoices/pdf-template'
|
||||
import { sendEmail, isResendConfigured } from '@/lib/email/resend'
|
||||
import {
|
||||
generateInvoiceEmailHtml,
|
||||
|
||||
@@ -3,7 +3,7 @@ import { NextResponse } from 'next/server'
|
||||
import { eventBus } from '@/lib/events'
|
||||
import { ensureInitialized } from '@/lib/init'
|
||||
import type { CreateInvoiceInput, EntityType, Invoice, CreditNote } from '@/types'
|
||||
import { getVatRules, calculateVat, calculateTotal } from '@/lib/invoice/vat-rules'
|
||||
import { getVatRules, calculateVat, calculateTotal } from '@/lib/invoices/vat-rules'
|
||||
import { fetchExchangeRate, convertToSEK } from '@/lib/currency/riksbanken'
|
||||
import {
|
||||
createCreditNoteJournalEntry,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { createClient } from '@/lib/supabase/server'
|
||||
import { NextResponse } from 'next/server'
|
||||
import { getBestInvoiceMatch } from '@/lib/invoice/invoice-matching'
|
||||
import { getBestInvoiceMatch } from '@/lib/invoices/invoice-matching'
|
||||
import type { Transaction } from '@/types'
|
||||
|
||||
/**
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
import { Badge } from '@/components/ui/badge'
|
||||
import { Separator } from '@/components/ui/separator'
|
||||
import { getVatTreatmentLabel } from '@/lib/invoice/vat-rules'
|
||||
import { getVatTreatmentLabel } from '@/lib/invoices/vat-rules'
|
||||
import { formatCurrency } from '@/lib/utils'
|
||||
import type { Customer, Currency, VatTreatment } from '@/types'
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@ vi.mock('@/lib/bookkeeping/transaction-entries', () => ({
|
||||
}))
|
||||
|
||||
const mockGetBestInvoiceMatch = vi.fn()
|
||||
vi.mock('@/lib/invoice/invoice-matching', () => ({
|
||||
vi.mock('@/lib/invoices/invoice-matching', () => ({
|
||||
getBestInvoiceMatch: (...args: unknown[]) => mockGetBestInvoiceMatch(...args),
|
||||
}))
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import type { SupabaseClient } from '@supabase/supabase-js'
|
||||
import { evaluateMappingRules } from '@/lib/bookkeeping/mapping-engine'
|
||||
import { createTransactionJournalEntry } from '@/lib/bookkeeping/transaction-entries'
|
||||
import { getBestInvoiceMatch } from '@/lib/invoice/invoice-matching'
|
||||
import { getBestInvoiceMatch } from '@/lib/invoices/invoice-matching'
|
||||
import type { Transaction } from '@/types'
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user