fix: resolve INK2/NE entity_type from companies table fallback (#217)
* fix: resolve INK2/NE entity_type from companies table fallback (#193) The entity_type check in INK2 and NE-bilaga engines read from company_settings where it is nullable, causing "only for aktiebolag" errors when the column is null. Now falls back to companies.entity_type (NOT NULL, always set). Reports page uses useCompany() context instead of /api/settings for tab visibility. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: address Greptile review — surface fallback errors, avoid direct mutation - Surface Supabase errors in entity_type fallback queries instead of silently swallowing them (ink2-engine, ne-engine) - Use spread instead of direct mutation on Supabase result object (settings route) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: use separate variable to avoid const reassignment in settings route 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
bca00cc5bd
commit
73fb97052b
@@ -9,6 +9,7 @@ import { Badge } from '@/components/ui/badge'
|
||||
import { Tabs, TabsList, TabsTrigger, TabsContent } from '@/components/ui/tabs'
|
||||
import { Download, AlertCircle, ChevronDown, ChevronRight, ArrowRight } from 'lucide-react'
|
||||
import { AccountNumber } from '@/components/ui/account-number'
|
||||
import { useCompany } from '@/contexts/CompanyContext'
|
||||
import { NEDeclarationView } from '@/components/reports/NEDeclarationView'
|
||||
import { INK2DeclarationView } from '@/components/reports/INK2DeclarationView'
|
||||
import { BankReconciliationView } from '@/components/reports/BankReconciliationView'
|
||||
@@ -48,8 +49,8 @@ export default function ReportsPage() {
|
||||
const [periods, setPeriods] = useState<FiscalPeriod[]>([])
|
||||
const [selectedPeriod, setSelectedPeriod] = useState('')
|
||||
const [activeTab, setActiveTab] = useState('trial-balance')
|
||||
const [entityType, setEntityType] = useState<string | null>(null)
|
||||
const [isLoadingInit, setIsLoadingInit] = useState(true)
|
||||
const { company } = useCompany()
|
||||
|
||||
// Drill-down state: when navigating from a report to the GL for a specific account
|
||||
const [glAccountFilter, setGlAccountFilter] = useState<string | null>(null)
|
||||
@@ -89,26 +90,14 @@ export default function ReportsPage() {
|
||||
}
|
||||
}
|
||||
|
||||
async function fetchEntityType() {
|
||||
try {
|
||||
const res = await fetch('/api/settings')
|
||||
const { data } = await res.json()
|
||||
if (data?.entity_type) {
|
||||
setEntityType(data.entity_type)
|
||||
}
|
||||
} catch {
|
||||
// Ignore - entity type is optional for tab visibility
|
||||
}
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
Promise.all([fetchPeriods(), fetchEntityType()]).finally(() => {
|
||||
fetchPeriods().finally(() => {
|
||||
setIsLoadingInit(false)
|
||||
})
|
||||
}, [])
|
||||
|
||||
const isEnskildFirma = entityType === 'enskild_firma'
|
||||
const isAktiebolag = entityType === 'aktiebolag'
|
||||
const isEnskildFirma = company?.entity_type === 'enskild_firma'
|
||||
const isAktiebolag = company?.entity_type === 'aktiebolag'
|
||||
|
||||
return (
|
||||
<div className="space-y-6">
|
||||
|
||||
@@ -26,7 +26,20 @@ export async function GET() {
|
||||
return NextResponse.json({ error: error.message }, { status: 500 })
|
||||
}
|
||||
|
||||
return NextResponse.json({ data })
|
||||
// Fall back to companies.entity_type if company_settings.entity_type is null
|
||||
let responseData = data
|
||||
if (data && !data.entity_type) {
|
||||
const { data: company } = await supabase
|
||||
.from('companies')
|
||||
.select('entity_type')
|
||||
.eq('id', companyId)
|
||||
.single()
|
||||
if (company?.entity_type) {
|
||||
responseData = { ...data, entity_type: company.entity_type }
|
||||
}
|
||||
}
|
||||
|
||||
return NextResponse.json({ data: responseData })
|
||||
}
|
||||
|
||||
export async function PUT(request: Request) {
|
||||
|
||||
@@ -714,8 +714,19 @@ export async function generateINK2Declaration(
|
||||
.eq('company_id', companyId)
|
||||
.single()
|
||||
|
||||
// Validate entity type
|
||||
if (settings?.entity_type !== 'aktiebolag') {
|
||||
// Resolve entity_type: prefer company_settings, fall back to companies table (NOT NULL, always reliable)
|
||||
let entityType = settings?.entity_type
|
||||
if (!entityType) {
|
||||
const { data: company, error: companyError } = await supabase
|
||||
.from('companies')
|
||||
.select('entity_type')
|
||||
.eq('id', companyId)
|
||||
.single()
|
||||
if (companyError) throw new Error(`Failed to resolve entity type: ${companyError.message}`)
|
||||
entityType = company?.entity_type
|
||||
}
|
||||
|
||||
if (entityType !== 'aktiebolag') {
|
||||
throw new Error('INK2 declaration is only for aktiebolag (limited company)')
|
||||
}
|
||||
|
||||
|
||||
@@ -179,8 +179,19 @@ export async function generateNEDeclaration(
|
||||
.eq('company_id', companyId)
|
||||
.single()
|
||||
|
||||
// Check if it's enskild firma
|
||||
if (settings?.entity_type !== 'enskild_firma') {
|
||||
// Resolve entity_type: prefer company_settings, fall back to companies table (NOT NULL, always reliable)
|
||||
let entityType = settings?.entity_type
|
||||
if (!entityType) {
|
||||
const { data: company, error: companyError } = await supabase
|
||||
.from('companies')
|
||||
.select('entity_type')
|
||||
.eq('id', companyId)
|
||||
.single()
|
||||
if (companyError) throw new Error(`Failed to resolve entity type: ${companyError.message}`)
|
||||
entityType = company?.entity_type
|
||||
}
|
||||
|
||||
if (entityType !== 'enskild_firma') {
|
||||
throw new Error('NE declaration is only for enskild firma (sole proprietorship)')
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user