Audit v4: VAT calc, SAF-T compliance, security hardening, frontend quality
Backend (17 files): - VAT: REP 25% deductibility (§42), EU reverse charge double-entry (IEUV/IEUY/IVY), IVY rate 0%→25%, VatReport Box C/D populated, Basis1 from real revenue - SAF-T: correct OECD namespace, closing balance net calc, zero-amount fallback, credit note auto-numbering (§52) - Security: BankingController CSRF state token + company auth check, attachment canonical path traversal check, discount 0-100% validation, deactivated product/customer update guard - Quality: redact bank API logs, remove dead code (VatCalcService, PaymentMatchingService), CompanyAggregate IEmit interfaces, fix URL encoding Frontend (15 files): - Fix double "kr." in AmountText and Dashboard Statistic components - Fix UserSettings Switch defaultChecked desync with Form state - Remove dual useCompany/useCompanyStore pattern (Dashboard, Moms, Bank) - Correct SKAT VAT deadline calculation per period type - Add half-yearly/yearly VAT period options - Guard console.error with import.meta.env.DEV - Use shared formatDate in BankConnectionsTab - Remove dead NONE vatCode check, purge 7 legacy VAT codes from type union - Migrate S25→U25, K25→I25 across all pages Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
a7d76df3a7
commit
8096a19081
32 changed files with 380 additions and 163 deletions
|
|
@ -51,8 +51,8 @@ export async function fetchGraphQL<TData, TVariables extends Record<string, unkn
|
|||
const data = await graphqlClient.request<TData>(query, variables, headers);
|
||||
return data;
|
||||
} catch (error) {
|
||||
// Log error for debugging
|
||||
console.error('GraphQL Error:', error);
|
||||
// Log error for debugging (dev only)
|
||||
if (import.meta.env.DEV) console.error('GraphQL Error:', error);
|
||||
|
||||
// Re-throw with more context
|
||||
if (error instanceof Error) {
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ import {
|
|||
DatePicker,
|
||||
} from 'antd';
|
||||
import { showSuccess, showError } from '@/lib/errorHandling';
|
||||
import { formatDate } from '@/lib/formatters';
|
||||
import type { Dayjs } from 'dayjs';
|
||||
import dayjs from 'dayjs';
|
||||
import {
|
||||
|
|
@ -64,13 +65,6 @@ function getStatusTag(status: BankConnection['status'], isActive: boolean) {
|
|||
return <Tag>{status}</Tag>;
|
||||
}
|
||||
|
||||
function formatDate(dateString: string) {
|
||||
return new Date(dateString).toLocaleDateString('da-DK', {
|
||||
year: 'numeric',
|
||||
month: 'short',
|
||||
day: 'numeric',
|
||||
});
|
||||
}
|
||||
|
||||
export default function BankConnectionsTab({ companyId }: BankConnectionsTabProps) {
|
||||
const [searchParams, setSearchParams] = useSearchParams();
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import { Typography, Tooltip } from 'antd';
|
||||
import { ArrowUpOutlined, ArrowDownOutlined, MinusOutlined } from '@ant-design/icons';
|
||||
import { formatCurrency } from '@/lib/formatters';
|
||||
import { formatCurrency, formatNumber } from '@/lib/formatters';
|
||||
import { accountingColors } from '@/styles/theme';
|
||||
import { typography, getAmountColor } from '@/styles/designTokens';
|
||||
|
||||
|
|
@ -77,7 +77,7 @@ export function AmountText({
|
|||
};
|
||||
|
||||
const formatAmount = (): string => {
|
||||
const formatted = formatCurrency(Math.abs(amount));
|
||||
const formatted = formatNumber(Math.abs(amount));
|
||||
// Always show +/- prefix for non-zero amounts (accessibility: not color-only)
|
||||
// When showSign is explicitly true, same behavior; kept for API compatibility
|
||||
const alwaysSign = showSign;
|
||||
|
|
|
|||
|
|
@ -138,11 +138,11 @@ export const VAT_RATES = {
|
|||
* Standard Danish VAT codes
|
||||
*/
|
||||
export const VAT_CODES = {
|
||||
S25: { code: 'S25', name: 'Udgående moms 25%', rate: 0.25, type: 'output' },
|
||||
K25: { code: 'K25', name: 'Indgående moms 25%', rate: 0.25, type: 'input' },
|
||||
U25: { code: 'U25', name: 'Udgående moms 25%', rate: 0.25, type: 'output' },
|
||||
I25: { code: 'I25', name: 'Indgående moms 25%', rate: 0.25, type: 'input' },
|
||||
E0: { code: 'E0', name: 'EU-varekøb 0%', rate: 0, type: 'eu' },
|
||||
U0: { code: 'U0', name: 'Eksport 0%', rate: 0, type: 'export' },
|
||||
NONE: { code: 'NONE', name: 'Ingen moms', rate: 0, type: 'none' },
|
||||
INGEN: { code: 'INGEN', name: 'Ingen moms', rate: 0, type: 'none' },
|
||||
} as const;
|
||||
|
||||
/**
|
||||
|
|
@ -298,11 +298,11 @@ export function generateSimpleDoubleEntry(input: SimpleBookingInput): GeneratedT
|
|||
|
||||
// For reverse charge (EU purchases), also credit output VAT
|
||||
if (vatConfig.reverseCharge && vatAmount > 0) {
|
||||
const outputVatAccount = vatCode === 'EU_VARE' ? VAT_ACCOUNTS.euVAT : VAT_ACCOUNTS.outputVAT;
|
||||
const outputVatAccount = vatCode === 'IEUV' ? VAT_ACCOUNTS.euVAT : VAT_ACCOUNTS.outputVAT;
|
||||
lines.push({
|
||||
accountId: `vat-output-${vatCode}`,
|
||||
accountNumber: outputVatAccount,
|
||||
accountName: vatCode === 'EU_VARE' ? 'EU-moms (erhvervelse)' : 'Udgående moms',
|
||||
accountName: vatCode === 'IEUV' ? 'EU-moms (erhvervelse)' : 'Udgående moms',
|
||||
description: `Moms: ${description}`,
|
||||
debit: 0,
|
||||
credit: vatAmount,
|
||||
|
|
@ -440,11 +440,11 @@ export function generateSplitDoubleEntry(input: SplitBookingInput): GeneratedTra
|
|||
|
||||
// For reverse charge, also credit output VAT
|
||||
if (vatConfig.reverseCharge && lineVat > 0) {
|
||||
const outputVatAccount = splitLine.vatCode === 'EU_VARE' ? VAT_ACCOUNTS.euVAT : VAT_ACCOUNTS.outputVAT;
|
||||
const outputVatAccount = splitLine.vatCode === 'IEUV' ? VAT_ACCOUNTS.euVAT : VAT_ACCOUNTS.outputVAT;
|
||||
generatedLines.push({
|
||||
accountId: `vat-output-${splitLine.vatCode}`,
|
||||
accountNumber: outputVatAccount,
|
||||
accountName: splitLine.vatCode === 'EU_VARE' ? 'EU-moms (erhvervelse)' : 'Udgående moms',
|
||||
accountName: splitLine.vatCode === 'IEUV' ? 'EU-moms (erhvervelse)' : 'Udgående moms',
|
||||
description: `Moms: ${description}`,
|
||||
debit: 0,
|
||||
credit: lineVat,
|
||||
|
|
@ -541,17 +541,17 @@ export function getSuggestedVATCode(accountNumber: string, isExpense: boolean):
|
|||
// Expenses typically use input VAT (K25)
|
||||
if (isExpense) {
|
||||
// Some expense types are typically VAT-exempt
|
||||
if (accountType === 'financial') return 'NONE';
|
||||
if (accountType === 'personnel') return 'NONE';
|
||||
return 'K25';
|
||||
if (accountType === 'financial') return 'INGEN';
|
||||
if (accountType === 'personnel') return 'INGEN';
|
||||
return 'I25';
|
||||
}
|
||||
|
||||
// Revenue typically uses output VAT (S25)
|
||||
// Revenue typically uses output VAT (U25)
|
||||
if (accountType === 'revenue') {
|
||||
return 'S25';
|
||||
return 'U25';
|
||||
}
|
||||
|
||||
return 'NONE';
|
||||
return 'INGEN';
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -159,11 +159,6 @@ function processTransactionLine(
|
|||
|
||||
const vatCode = line.vatCode;
|
||||
|
||||
// Skip lines without VAT relevance
|
||||
if (vatCode === 'NONE') {
|
||||
return null;
|
||||
}
|
||||
|
||||
const codeConfig = VAT_CODE_CONFIG[vatCode];
|
||||
|
||||
// Calculate net amount (amount without VAT)
|
||||
|
|
|
|||
|
|
@ -33,7 +33,6 @@ import dayjs from 'dayjs';
|
|||
import { useNavigate } from 'react-router-dom';
|
||||
import { useCompany } from '@/hooks/useCompany';
|
||||
import { useReconciliationStore } from '@/stores/reconciliationStore';
|
||||
import { useCompanyStore } from '@/stores/companyStore';
|
||||
import { useActiveBankConnections } from '@/api/queries/bankConnectionQueries';
|
||||
import { usePendingBankTransactions } from '@/api/queries/bankTransactionQueries';
|
||||
import { useActiveAccounts } from '@/api/queries/accountQueries';
|
||||
|
|
@ -69,12 +68,11 @@ interface MatchSuggestion {
|
|||
export default function Bankafstemning() {
|
||||
const { company } = useCompany();
|
||||
const navigate = useNavigate();
|
||||
const { activeCompany } = useCompanyStore();
|
||||
|
||||
// Fetch data from API
|
||||
const { data: bankConnections = [], isLoading: connectionsLoading } = useActiveBankConnections(activeCompany?.id);
|
||||
const { data: pendingTransactions = [], isLoading: transactionsLoading } = usePendingBankTransactions(activeCompany?.id);
|
||||
const { data: activeAccounts = [] } = useActiveAccounts(activeCompany?.id);
|
||||
const { data: bankConnections = [], isLoading: connectionsLoading } = useActiveBankConnections(company?.id);
|
||||
const { data: pendingTransactions = [], isLoading: transactionsLoading } = usePendingBankTransactions(company?.id);
|
||||
const { data: activeAccounts = [] } = useActiveAccounts(company?.id);
|
||||
|
||||
const isLoading = connectionsLoading || transactionsLoading;
|
||||
|
||||
|
|
@ -82,7 +80,7 @@ export default function Bankafstemning() {
|
|||
const bankAccounts = bankConnections.flatMap(conn =>
|
||||
(conn.accounts || []).map(acc => ({
|
||||
id: acc.accountId,
|
||||
companyId: activeCompany?.id || '',
|
||||
companyId: company?.id || '',
|
||||
name: acc.name || acc.iban,
|
||||
bankName: conn.aspspName,
|
||||
accountNumber: acc.iban,
|
||||
|
|
@ -697,9 +695,9 @@ export default function Bankafstemning() {
|
|||
placeholder="Vælg momskode"
|
||||
allowClear
|
||||
options={[
|
||||
{ value: 'K25', label: 'K25 - Indgående moms 25%' },
|
||||
{ value: 'S25', label: 'S25 - Udgående moms 25%' },
|
||||
{ value: 'NONE', label: 'Ingen moms' },
|
||||
{ value: 'I25', label: 'I25 - Indgående moms 25%' },
|
||||
{ value: 'U25', label: 'U25 - Udgående moms 25%' },
|
||||
{ value: 'INGEN', label: 'Ingen moms' },
|
||||
]}
|
||||
/>
|
||||
</Form.Item>
|
||||
|
|
|
|||
|
|
@ -10,7 +10,6 @@ import { Line, Pie, Column } from '@ant-design/charts';
|
|||
import { Link } from 'react-router-dom';
|
||||
import dayjs from 'dayjs';
|
||||
import { useCompany } from '@/hooks/useCompany';
|
||||
import { useCompanyStore } from '@/stores/companyStore';
|
||||
import { usePeriodStore } from '@/stores/periodStore';
|
||||
import { useAccountBalances } from '@/api/queries/accountQueries';
|
||||
import { useInvoices } from '@/api/queries/invoiceQueries';
|
||||
|
|
@ -45,7 +44,6 @@ interface RecentTransaction {
|
|||
|
||||
export default function Dashboard() {
|
||||
const { company } = useCompany();
|
||||
const { activeCompany } = useCompanyStore();
|
||||
const { currentFiscalYear } = usePeriodStore();
|
||||
|
||||
// Define date interval - always format as YYYY-MM-DD for GraphQL DateOnly type
|
||||
|
|
@ -57,16 +55,16 @@ export default function Dashboard() {
|
|||
: dayjs().endOf('year').format('YYYY-MM-DD');
|
||||
|
||||
const { data: balances = [], isLoading: balancesLoading } = useAccountBalances(
|
||||
activeCompany?.id,
|
||||
company?.id,
|
||||
currentFiscalYear ? {
|
||||
startDate: dayjs(currentFiscalYear.startDate),
|
||||
endDate: dayjs(currentFiscalYear.endDate),
|
||||
} : undefined
|
||||
);
|
||||
|
||||
const { data: invoices = [], isLoading: invoicesLoading } = useInvoices(activeCompany?.id);
|
||||
const { data: invoices = [], isLoading: invoicesLoading } = useInvoices(company?.id);
|
||||
const { data: vatReport, isLoading: vatLoading } = useVatReport(
|
||||
activeCompany?.id,
|
||||
company?.id,
|
||||
periodStart,
|
||||
periodEnd
|
||||
);
|
||||
|
|
@ -252,7 +250,6 @@ export default function Dashboard() {
|
|||
value={metrics.cashPosition}
|
||||
precision={2}
|
||||
prefix={<BankOutlined />}
|
||||
suffix="kr."
|
||||
formatter={(value) => formatCurrency(value as number)}
|
||||
/>
|
||||
<div style={{ marginTop: 8 }}>
|
||||
|
|
@ -270,7 +267,6 @@ export default function Dashboard() {
|
|||
title="Tilgodehavender"
|
||||
value={metrics.accountsReceivable}
|
||||
precision={2}
|
||||
suffix="kr."
|
||||
valueStyle={{ color: accountingColors.credit }}
|
||||
formatter={(value) => formatCurrency(value as number)}
|
||||
/>
|
||||
|
|
@ -294,7 +290,6 @@ export default function Dashboard() {
|
|||
title="Kreditorer"
|
||||
value={metrics.accountsPayable}
|
||||
precision={2}
|
||||
suffix="kr."
|
||||
valueStyle={{ color: accountingColors.debit }}
|
||||
formatter={(value) => formatCurrency(value as number)}
|
||||
/>
|
||||
|
|
@ -313,7 +308,6 @@ export default function Dashboard() {
|
|||
title="Moms til betaling"
|
||||
value={metrics.vatLiability}
|
||||
precision={2}
|
||||
suffix="kr."
|
||||
formatter={(value) => formatCurrency(value as number)}
|
||||
/>
|
||||
<div style={{ marginTop: 8 }}>
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@ export default function Eksport() {
|
|||
}
|
||||
} catch (error) {
|
||||
showError('Der opstod en fejl under eksport');
|
||||
console.error('SAF-T export error:', error);
|
||||
if (import.meta.env.DEV) console.error('SAF-T export error:', error);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -223,7 +223,7 @@ export default function Fakturaer() {
|
|||
const handleAddLine = () => {
|
||||
setEditingLine(null);
|
||||
lineForm.resetFields();
|
||||
lineForm.setFieldsValue({ quantity: 1, vatCode: 'S25' });
|
||||
lineForm.setFieldsValue({ quantity: 1, vatCode: 'U25' });
|
||||
setIsLineModalOpen(true);
|
||||
};
|
||||
|
||||
|
|
@ -862,7 +862,7 @@ export default function Fakturaer() {
|
|||
lineForm.setFieldsValue({
|
||||
description: product.description || product.name,
|
||||
unitPrice: product.unitPrice,
|
||||
vatCode: product.vatCode === 'U25' ? 'S25' : product.vatCode,
|
||||
vatCode: product.vatCode,
|
||||
unit: product.unit || undefined,
|
||||
});
|
||||
}
|
||||
|
|
@ -930,7 +930,7 @@ export default function Fakturaer() {
|
|||
>
|
||||
<Select
|
||||
options={[
|
||||
{ value: 'S25', label: 'S25 - 25% moms' },
|
||||
{ value: 'U25', label: 'U25 - 25% moms' },
|
||||
{ value: 'U0', label: 'U0 - Momsfrit' },
|
||||
{ value: 'UEU', label: 'UEU - EU-salg' },
|
||||
{ value: 'UEXP', label: 'UEXP - Eksport' },
|
||||
|
|
|
|||
|
|
@ -424,8 +424,8 @@ export default function Kontooversigt() {
|
|||
allowClear
|
||||
placeholder="Vælg..."
|
||||
options={[
|
||||
{ value: 'S25', label: 'S25 - Udgående (Salg)' },
|
||||
{ value: 'K25', label: 'K25 - Indgående (Køb)' },
|
||||
{ value: 'U25', label: 'U25 - Udgående (Salg)' },
|
||||
{ value: 'I25', label: 'I25 - Indgående (Køb)' },
|
||||
{ value: 'E0', label: 'E0 - EU-salg' },
|
||||
{ value: 'U0', label: 'U0 - Eksport' },
|
||||
]}
|
||||
|
|
|
|||
|
|
@ -211,7 +211,7 @@ export default function Kreditnotaer() {
|
|||
const handleAddLine = () => {
|
||||
setEditingLine(null);
|
||||
lineForm.resetFields();
|
||||
lineForm.setFieldsValue({ quantity: 1, vatCode: 'S25' });
|
||||
lineForm.setFieldsValue({ quantity: 1, vatCode: 'U25' });
|
||||
setIsLineModalOpen(true);
|
||||
};
|
||||
|
||||
|
|
@ -854,7 +854,7 @@ export default function Kreditnotaer() {
|
|||
>
|
||||
<Select
|
||||
options={[
|
||||
{ value: 'S25', label: 'S25 - 25% moms' },
|
||||
{ value: 'U25', label: 'U25 - 25% moms' },
|
||||
{ value: 'U0', label: 'U0 - Momsfrit' },
|
||||
{ value: 'UEU', label: 'UEU - EU-salg' },
|
||||
{ value: 'UEXP', label: 'UEXP - Eksport' },
|
||||
|
|
|
|||
|
|
@ -26,7 +26,6 @@ import {
|
|||
import { Pie } from '@ant-design/charts';
|
||||
import dayjs from 'dayjs';
|
||||
import { useCompany } from '@/hooks/useCompany';
|
||||
import { useCompanyStore } from '@/stores/companyStore';
|
||||
import { useVatReport } from '@/api/queries/vatQueries';
|
||||
import { formatCurrency, formatPeriod } from '@/lib/formatters';
|
||||
import { accountingColors } from '@/styles/theme';
|
||||
|
|
@ -47,18 +46,25 @@ interface VATBox {
|
|||
|
||||
export default function Momsindberetning() {
|
||||
const { company } = useCompany();
|
||||
const { activeCompany } = useCompanyStore();
|
||||
const [selectedPeriod, setSelectedPeriod] = useState<dayjs.Dayjs>(
|
||||
dayjs().subtract(1, 'month').startOf('month')
|
||||
);
|
||||
const [isPreviewOpen, setIsPreviewOpen] = useState(false);
|
||||
const [periodType, setPeriodType] = useState<'monthly' | 'quarterly'>('quarterly');
|
||||
const [periodType, setPeriodType] = useState<'monthly' | 'quarterly' | 'half-yearly' | 'yearly'>('quarterly');
|
||||
|
||||
// Calculate period dates based on selection
|
||||
const periodStart = useMemo(() => {
|
||||
if (periodType === 'quarterly') {
|
||||
return selectedPeriod.startOf('quarter').format('YYYY-MM-DD');
|
||||
}
|
||||
if (periodType === 'half-yearly') {
|
||||
const month = selectedPeriod.month(); // 0-indexed
|
||||
const halfStart = month < 6 ? 0 : 6;
|
||||
return selectedPeriod.month(halfStart).startOf('month').format('YYYY-MM-DD');
|
||||
}
|
||||
if (periodType === 'yearly') {
|
||||
return selectedPeriod.startOf('year').format('YYYY-MM-DD');
|
||||
}
|
||||
return selectedPeriod.startOf('month').format('YYYY-MM-DD');
|
||||
}, [selectedPeriod, periodType]);
|
||||
|
||||
|
|
@ -66,12 +72,20 @@ export default function Momsindberetning() {
|
|||
if (periodType === 'quarterly') {
|
||||
return selectedPeriod.endOf('quarter').format('YYYY-MM-DD');
|
||||
}
|
||||
if (periodType === 'half-yearly') {
|
||||
const month = selectedPeriod.month(); // 0-indexed
|
||||
const halfEnd = month < 6 ? 5 : 11;
|
||||
return selectedPeriod.month(halfEnd).endOf('month').format('YYYY-MM-DD');
|
||||
}
|
||||
if (periodType === 'yearly') {
|
||||
return selectedPeriod.endOf('year').format('YYYY-MM-DD');
|
||||
}
|
||||
return selectedPeriod.endOf('month').format('YYYY-MM-DD');
|
||||
}, [selectedPeriod, periodType]);
|
||||
|
||||
// Fetch VAT report from backend
|
||||
const { data: vatReport, isLoading, error } = useVatReport(
|
||||
activeCompany?.id,
|
||||
company?.id,
|
||||
periodStart,
|
||||
periodEnd
|
||||
);
|
||||
|
|
@ -255,20 +269,44 @@ export default function Momsindberetning() {
|
|||
<Select
|
||||
value={periodType}
|
||||
onChange={setPeriodType}
|
||||
style={{ width: 120 }}
|
||||
style={{ width: 140 }}
|
||||
options={[
|
||||
{ value: 'monthly', label: 'Månedlig' },
|
||||
{ value: 'quarterly', label: 'Kvartalsvis' },
|
||||
{ value: 'half-yearly', label: 'Halvårlig' },
|
||||
{ value: 'yearly', label: 'Årlig' },
|
||||
]}
|
||||
/>
|
||||
<DatePicker
|
||||
picker={periodType === 'quarterly' ? 'quarter' : 'month'}
|
||||
picker={periodType === 'quarterly' ? 'quarter' : periodType === 'yearly' ? 'year' : 'month'}
|
||||
value={selectedPeriod}
|
||||
onChange={(date) => date && setSelectedPeriod(date)}
|
||||
format={periodType === 'quarterly' ? '[Q]Q YYYY' : 'MMMM YYYY'}
|
||||
format={
|
||||
periodType === 'quarterly' ? '[Q]Q YYYY'
|
||||
: periodType === 'yearly' ? 'YYYY'
|
||||
: 'MMMM YYYY'
|
||||
}
|
||||
/>
|
||||
<Tag color="blue">
|
||||
Frist: {dayjs(selectedPeriod).add(1, 'month').endOf('month').format('D. MMMM YYYY')}
|
||||
Frist: {(() => {
|
||||
const pEnd = dayjs(periodEnd);
|
||||
switch (periodType) {
|
||||
case 'monthly':
|
||||
// 25th of next month
|
||||
return pEnd.add(1, 'month').date(25).format('D. MMMM YYYY');
|
||||
case 'quarterly':
|
||||
// 1st day of 2nd month after quarter end
|
||||
return pEnd.add(2, 'month').startOf('month').format('D. MMMM YYYY');
|
||||
case 'half-yearly':
|
||||
// 1st day of 3rd month after half-year end
|
||||
return pEnd.add(3, 'month').startOf('month').format('D. MMMM YYYY');
|
||||
case 'yearly':
|
||||
// 6 months after fiscal year end
|
||||
return pEnd.add(6, 'month').format('D. MMMM YYYY');
|
||||
default:
|
||||
return pEnd.add(1, 'month').endOf('month').format('D. MMMM YYYY');
|
||||
}
|
||||
})()}
|
||||
</Tag>
|
||||
{vatReport && (
|
||||
<Tag color="green">{vatReport.transactionCount} transaktioner</Tag>
|
||||
|
|
|
|||
|
|
@ -178,7 +178,7 @@ export default function Ordrer() {
|
|||
addLineForm.resetFields();
|
||||
addLineForm.setFieldsValue({
|
||||
quantity: 1,
|
||||
vatCode: 'S25',
|
||||
vatCode: 'U25',
|
||||
});
|
||||
setAddLineMode('product');
|
||||
setSelectedProductId(null);
|
||||
|
|
@ -193,7 +193,7 @@ export default function Ordrer() {
|
|||
description: product.name,
|
||||
unitPrice: product.unitPrice,
|
||||
unit: product.unit || 'stk',
|
||||
vatCode: product.vatCode || 'S25',
|
||||
vatCode: product.vatCode || 'U25',
|
||||
});
|
||||
}
|
||||
};
|
||||
|
|
@ -825,7 +825,7 @@ export default function Ordrer() {
|
|||
addLineForm.resetFields();
|
||||
addLineForm.setFieldsValue({
|
||||
quantity: 1,
|
||||
vatCode: 'S25',
|
||||
vatCode: 'U25',
|
||||
});
|
||||
}}
|
||||
optionType="button"
|
||||
|
|
@ -918,7 +918,7 @@ export default function Ordrer() {
|
|||
<Select
|
||||
disabled={addLineMode === 'product' && !!selectedProductId}
|
||||
options={[
|
||||
{ value: 'S25', label: 'S25 - Salgsmoms 25%' },
|
||||
{ value: 'U25', label: 'U25 - Salgsmoms 25%' },
|
||||
{ value: 'S0', label: 'S0 - Momsfrit salg' },
|
||||
]}
|
||||
/>
|
||||
|
|
|
|||
|
|
@ -308,7 +308,7 @@ export default function UserSettings() {
|
|||
Modtag vigtige opdateringer om din konto
|
||||
</Text>
|
||||
</div>
|
||||
<Switch defaultChecked={mockUser.notifications.email} />
|
||||
<Switch />
|
||||
</div>
|
||||
</Form.Item>
|
||||
|
||||
|
|
@ -324,7 +324,7 @@ export default function UserSettings() {
|
|||
Få en opsummering af ugens bogføring hver mandag
|
||||
</Text>
|
||||
</div>
|
||||
<Switch defaultChecked={mockUser.notifications.weeklyReport} />
|
||||
<Switch />
|
||||
</div>
|
||||
</Form.Item>
|
||||
|
||||
|
|
@ -340,7 +340,7 @@ export default function UserSettings() {
|
|||
Få besked når momsfrister eller andre deadlines nærmer sig
|
||||
</Text>
|
||||
</div>
|
||||
<Switch defaultChecked={mockUser.notifications.deadlineReminders} />
|
||||
<Switch />
|
||||
</div>
|
||||
</Form.Item>
|
||||
|
||||
|
|
@ -360,7 +360,7 @@ export default function UserSettings() {
|
|||
Modtag notifikationer direkte i browseren
|
||||
</Text>
|
||||
</div>
|
||||
<Switch defaultChecked={mockUser.notifications.browser} />
|
||||
<Switch />
|
||||
</div>
|
||||
</Form.Item>
|
||||
|
||||
|
|
|
|||
|
|
@ -19,15 +19,7 @@ export type VATCode =
|
|||
| 'IVV' // Import varer verden (0%)
|
||||
| 'IVY' // Import ydelser verden (0%)
|
||||
| 'REP' // Repræsentation (25%, 25% fradrag)
|
||||
| 'INGEN' // Ingen moms
|
||||
// Legacy codes kept for backwards compatibility with other modules
|
||||
| 'S25' // @deprecated Use U25
|
||||
| 'K25' // @deprecated Use I25
|
||||
| 'EU_VARE' // @deprecated Use IEUV
|
||||
| 'EU_YDELSE' // @deprecated Use IEUY
|
||||
| 'MOMSFRI' // @deprecated Use INGEN
|
||||
| 'EKSPORT' // @deprecated Use UEXP
|
||||
| 'NONE'; // @deprecated Use INGEN
|
||||
| 'INGEN'; // Ingen moms
|
||||
|
||||
/**
|
||||
* VAT code type classification
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue