* feat: add bike benefit handling and optional vacation accrual - Introduced bike benefit (cykelförmån) with calculations for annual market value and monthly taxable value. - Updated schemas to include new benefit types and validation rules. - Implemented API routes for creating, updating, and deleting employee benefits. - Enhanced salary calculation logic to accommodate new vacation rule options, including a 'none' option for no accrual. - Added UI components for managing employee benefits, including input for bike benefit specifics. - Created database migrations for employee benefits and updated salary line items to support new benefit types. * chore: remove Langfuse env var checks Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * feat: enhance OAuth callback URL handling and update default scopes for Visma integration * feat: remove trade_name field and simplify company naming in invoices * refactor: destructure canWrite from useCanWrite for consistency across components * feat: enhance PATCH endpoint to validate existing benefits and handle bike benefit updates * feat: add missing label for bike benefit in salary line item types --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
42 lines
1.2 KiB
TypeScript
42 lines
1.2 KiB
TypeScript
import { NextResponse } from 'next/server'
|
|
import { createClient } from '@/lib/supabase/server'
|
|
import { fetchTaxTableRates, TaxTableUnavailableError } from '@/lib/salary/tax-tables'
|
|
|
|
/**
|
|
* Probe Skatteverket's open data API to confirm tax tables are reachable.
|
|
* Used by the salary settings page to surface that fetching is automatic.
|
|
*/
|
|
export async function GET(request: Request) {
|
|
const supabase = await createClient()
|
|
const { data: { user } } = await supabase.auth.getUser()
|
|
if (!user) return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
|
|
|
|
const { searchParams } = new URL(request.url)
|
|
const year = parseInt(searchParams.get('year') || String(new Date().getFullYear()))
|
|
|
|
try {
|
|
const { source } = await fetchTaxTableRates(year, 30, 1)
|
|
return NextResponse.json({
|
|
data: {
|
|
year,
|
|
source,
|
|
reachable: source === 'api',
|
|
checkedAt: new Date().toISOString(),
|
|
},
|
|
})
|
|
} catch (err) {
|
|
if (err instanceof TaxTableUnavailableError) {
|
|
return NextResponse.json({
|
|
data: {
|
|
year,
|
|
source: 'unavailable' as const,
|
|
reachable: false,
|
|
checkedAt: new Date().toISOString(),
|
|
message: err.message,
|
|
},
|
|
})
|
|
}
|
|
throw err
|
|
}
|
|
}
|