Supp/invoice bfl errors (#390)
* feat(accounting): update accounting method validation and messaging for aktiebolag and enskild firma * Remove AI subsystem and related code - Deleted AI proposals and requests persistence logic from `lib/ai/proposals/persist.ts`. - Removed re-validation logic for proposals in `lib/ai/proposals/re-validate.ts`. - Cleaned up schemas related to AI flows in `lib/api/schemas.ts`. - Removed AI-related fields from bookkeeping engine in `lib/bookkeeping/engine.ts`. - Eliminated AI event types from `lib/events/types.ts`. - Updated tests to reflect the removal of AI-related functionality in `lib/extensions/__tests__/sectors.test.ts`. - Adjusted initialization logic in `lib/init.ts` to exclude AI proposal handler registration. - Cleaned up transaction ingestion logic in `lib/transactions/ingest.ts` to remove AI flow checks. - Updated helper functions in `tests/helpers.ts` to remove AI-related settings. - Removed AI-related types and interfaces from `types/index.ts`. - Added migration script to drop AI-related tables and settings from the database. * fix(migrations): ensure foreign key constraint is dropped before removing AI tables * feat(invoice-inbox): implement deterministic invoice field extraction and inbox provisioning - Added `extract-invoice-fields.ts` for extracting fields from PDF invoices using regex and pdfjs-dist, replacing the previous AI classifier. - Introduced `inbox-provisioning.ts` to manage company inbox addresses and rotation of inboxes using Supabase RPCs. - Created `resend-inbound.ts` for handling inbound email events and attachments via the Resend API. - Defined the extension manifest for the invoice inbox, specifying required environment variables and descriptions. - Migrated database schema to remove AI-related columns and tighten the status enum in `invoice_inbox_items`. * feat(invoice-inbox): remove AI-specific columns and tighten status enum * fix(skattekonto): remove manual entry creation reference from transaction input * fix(schemas): remove accounting method validation for aktiebolag in UpdateSettingsSchema
This commit is contained in:
@@ -519,19 +519,8 @@ export default function SwipeCategorizationView({
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Document upload / pre-attached document */}
|
||||
{pendingInboxItemId && currentTransaction.matched_inbox_item?.document_id ? (
|
||||
<div className="rounded-lg border bg-success/5 border-success/30 px-3 py-2.5">
|
||||
<div className="flex items-center gap-2">
|
||||
<Paperclip className="h-4 w-4 text-success" />
|
||||
<span className="text-sm font-medium">Underlag bifogat</span>
|
||||
<Check className="h-4 w-4 text-success" />
|
||||
</div>
|
||||
<p className="text-xs text-muted-foreground mt-1">
|
||||
Dokumentet från inkorgen länkas automatiskt till verifikationen.
|
||||
</p>
|
||||
</div>
|
||||
) : (
|
||||
{/* Document upload */}
|
||||
{(
|
||||
<div className="rounded-lg border">
|
||||
<button
|
||||
type="button"
|
||||
@@ -711,55 +700,6 @@ export default function SwipeCategorizationView({
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Document Match from Inbox */}
|
||||
{currentTransaction.matched_inbox_item && (
|
||||
<div className="p-4 rounded-lg border-2 border-primary/40 bg-primary/5 space-y-2">
|
||||
<div className="flex items-center justify-between">
|
||||
<div className="flex items-center gap-2 text-primary">
|
||||
<Paperclip className="h-5 w-5" />
|
||||
<span className="font-semibold text-sm">
|
||||
{currentTransaction.matched_inbox_item.document_type === 'receipt'
|
||||
? 'Matchat kvitto'
|
||||
: currentTransaction.matched_inbox_item.document_type === 'supplier_invoice'
|
||||
? 'Matchad leverantörsfaktura'
|
||||
: 'Matchat dokument'}
|
||||
</span>
|
||||
</div>
|
||||
{currentTransaction.matched_inbox_item.match_confidence != null && (
|
||||
<Badge variant="outline" className="text-primary border-primary">
|
||||
{Math.round(currentTransaction.matched_inbox_item.match_confidence * 100)}%
|
||||
</Badge>
|
||||
)}
|
||||
</div>
|
||||
<div className="text-sm">
|
||||
{(() => {
|
||||
const ext = currentTransaction.matched_inbox_item.extracted_data as Record<string, unknown> | null
|
||||
if (!ext) return null
|
||||
const supplierName = (ext as { supplier?: { name?: string } })?.supplier?.name
|
||||
const merchantName = (ext as { merchant?: { name?: string } })?.merchant?.name
|
||||
const totals = ext as { totals?: { total?: number } }
|
||||
return (
|
||||
<>
|
||||
{(supplierName || merchantName) && (
|
||||
<p className="font-medium">{supplierName || merchantName}</p>
|
||||
)}
|
||||
{totals?.totals?.total != null && (
|
||||
<p className="text-muted-foreground">
|
||||
{formatCurrency(totals.totals.total)}
|
||||
</p>
|
||||
)}
|
||||
</>
|
||||
)
|
||||
})()}
|
||||
{currentTransaction.matched_inbox_item.suggested_template_id && (
|
||||
<p className="text-xs text-primary mt-1">
|
||||
Mall: {currentTransaction.matched_inbox_item.suggested_template_id}
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Warnings */}
|
||||
{warnings.length > 0 && (
|
||||
<div className="space-y-2 pt-4 border-t">
|
||||
@@ -799,25 +739,6 @@ export default function SwipeCategorizationView({
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Document template match — primary action when inbox item has a suggested template */}
|
||||
{currentTransaction.matched_inbox_item?.suggested_template_id && (() => {
|
||||
const inboxItem = currentTransaction.matched_inbox_item
|
||||
if (!inboxItem?.suggested_template_id) return null
|
||||
const tmplId = inboxItem.suggested_template_id
|
||||
const template = getTemplateById(tmplId)
|
||||
if (!template) return null
|
||||
return (
|
||||
<Button
|
||||
className="w-full"
|
||||
onClick={() => handleTemplateSelect(tmplId, inboxItem.id)}
|
||||
disabled={isProcessing}
|
||||
>
|
||||
<Paperclip className="mr-2 h-4 w-4" />
|
||||
Bokför som {template.name_sv}
|
||||
</Button>
|
||||
)
|
||||
})()}
|
||||
|
||||
{/* Invoice match button - primary action when there's a match */}
|
||||
{currentTransaction.potential_invoice && onMatchInvoice && (
|
||||
<Button
|
||||
|
||||
@@ -6,7 +6,7 @@ import { Button } from '@/components/ui/button'
|
||||
import { Badge } from '@/components/ui/badge'
|
||||
import { Checkbox } from '@/components/ui/checkbox'
|
||||
import { cn, formatCurrency, formatDate } from '@/lib/utils'
|
||||
import { ArrowUpRight, ArrowDownRight, FileText, Loader2, Paperclip, Trash2 } from 'lucide-react'
|
||||
import { ArrowUpRight, ArrowDownRight, FileText, Loader2, Trash2 } from 'lucide-react'
|
||||
import { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider } from '@/components/ui/info-tooltip'
|
||||
import { getAccountName, formatAccountWithName } from '@/lib/bookkeeping/client-account-names'
|
||||
import { getTemplateById } from '@/lib/bookkeeping/booking-templates'
|
||||
@@ -59,7 +59,6 @@ export default function TransactionInboxCard({
|
||||
const topSuggestion = suggestions?.[0]
|
||||
const isUncategorized = transaction.is_business === null && !transaction.journal_entry_id
|
||||
const showCheckbox = isBatchMode && isUncategorized
|
||||
const hasDocumentMatch = !!transaction.matched_inbox_item
|
||||
const isDeletable = !transaction.journal_entry_id
|
||||
|
||||
function handleSuggestionClick(suggestion: SuggestedCategory) {
|
||||
@@ -116,16 +115,7 @@ export default function TransactionInboxCard({
|
||||
</div>
|
||||
<div className="min-w-0">
|
||||
<p className="font-medium truncate">{transaction.description}</p>
|
||||
<div className="flex items-center gap-2">
|
||||
<p className="text-sm text-muted-foreground">{formatDate(transaction.date)}</p>
|
||||
{hasDocumentMatch && (
|
||||
<Badge variant="secondary" className="text-xs gap-1">
|
||||
<Paperclip className="h-3 w-3" />
|
||||
{transaction.matched_inbox_item!.document_type === 'receipt' ? 'Kvitto' :
|
||||
transaction.matched_inbox_item!.document_type === 'supplier_invoice' ? 'Faktura' : 'Dokument'}
|
||||
</Badge>
|
||||
)}
|
||||
</div>
|
||||
<p className="text-sm text-muted-foreground">{formatDate(transaction.date)}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
import type { Transaction, TransactionCategory, Invoice, Customer, SupplierInvoice, VatTreatment, InvoiceInboxItem } from '@/types'
|
||||
import type { Transaction, TransactionCategory, Invoice, Customer, SupplierInvoice, VatTreatment } from '@/types'
|
||||
|
||||
// Shared transaction type with potential invoice data
|
||||
export interface TransactionWithInvoice extends Transaction {
|
||||
potential_invoice?: Invoice & { customer?: Customer }
|
||||
potential_supplier_invoice?: SupplierInvoice
|
||||
matched_inbox_item?: InvoiceInboxItem
|
||||
}
|
||||
|
||||
// Page view modes
|
||||
|
||||
Reference in New Issue
Block a user