feat(worklist): the next Skatteverket payment with bankgiro, OCR and due date under Att göra on Hem (#2435)
Part (a) of #2187. A twelfth worklist category, skattekonto_payment_due: the earliest upcoming skattekonto charge whose sum exceeds the last synced saldo, computed once in lib/worklist (server-side twin of the /skattekonto page's Nästa dragning math) and rendered as one Betala row on Hem with the shortfall, bankgiro 5050-1055, the OCR reference and the due date. The row appears only when money has to move: a saldo that covers the charge yields nothing, and no upcoming charge yields nothing. Ignored rows take part, since Skatteverket draws them regardless of our flag. Without a balance snapshot the full charge is the amount. Without an org number the row keeps its bankgiro and date and drops the OCR. No table, route or migration: /api/worklist/counts picks the category up through getWorklistCounts, and Hem passes the computed row into the same options wave as the expense payouts. Part (b), a betalfil for the skattekonto payment, stays a follow-up: the existing payment-file route is AGI-scoped. Claude-Session: https://claude.ai/code/session_0179bdetHyofL6ATfQxB5wP5 Co-authored-by: Jakob Wennberg <311770904+jakobwennberg-oss@users.noreply.github.com> Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Jakob Wennberg
Claude Fable 5.1
parent
a7dcaac6ad
commit
20925f6c65
@@ -30,7 +30,12 @@ import {
|
||||
ShieldCheck,
|
||||
Stamp,
|
||||
} from 'lucide-react'
|
||||
import type { ExpensePayoutDue, SuggestedMatch, WorklistCounts } from '@/lib/worklist/types'
|
||||
import type {
|
||||
ExpensePayoutDue,
|
||||
SkattekontoPaymentDue,
|
||||
SuggestedMatch,
|
||||
WorklistCounts,
|
||||
} from '@/lib/worklist/types'
|
||||
|
||||
/**
|
||||
* AttGoraSection: the dashboard's unified worklist ("Att göra").
|
||||
@@ -57,6 +62,8 @@ interface AttGoraSectionProps {
|
||||
suggestedMatches: SuggestedMatch[]
|
||||
/** People owed for registered, unpaid utlägg: one Betala row each. */
|
||||
expensePayouts?: ExpensePayoutDue[]
|
||||
/** The next skattekonto charge the balance does not cover: one Betala row. */
|
||||
skattekontoPayment?: SkattekontoPaymentDue | null
|
||||
expiringBankConnections?: ExpiringBankConnection[]
|
||||
/**
|
||||
* True while the setup checklist is open and the company has zero posted
|
||||
@@ -119,6 +126,7 @@ export default function AttGoraSection({
|
||||
worklist,
|
||||
suggestedMatches,
|
||||
expensePayouts = [],
|
||||
skattekontoPayment = null,
|
||||
expiringBankConnections = [],
|
||||
emptyLedger = false,
|
||||
hasActiveBankConnection = true,
|
||||
@@ -218,7 +226,7 @@ export default function AttGoraSection({
|
||||
counts.book_skattekonto > 0 ||
|
||||
showInboxDocuments ||
|
||||
matches.length > 0
|
||||
const betalaRows = expensePayouts.length > 0
|
||||
const betalaRows = expensePayouts.length > 0 || skattekontoPayment !== null
|
||||
const granskaRows =
|
||||
counts.supplier_invoice_approval > 0 ||
|
||||
counts.verifikat_missing_document > 0 ||
|
||||
@@ -396,6 +404,31 @@ export default function AttGoraSection({
|
||||
<div>
|
||||
<BandHeader>{t('band_betala')}</BandHeader>
|
||||
<div>
|
||||
{skattekontoPayment && (
|
||||
<WorklistRow
|
||||
href="/skattekonto"
|
||||
icon={Landmark}
|
||||
label={t('row_skattekonto_payment')}
|
||||
detail={
|
||||
skattekontoPayment.ocr
|
||||
? t('row_skattekonto_payment_detail', {
|
||||
bankgiro: skattekontoPayment.bankgiro,
|
||||
ocr: skattekontoPayment.ocr,
|
||||
date: formatDate(skattekontoPayment.due),
|
||||
})
|
||||
: t('row_skattekonto_payment_detail_no_ocr', {
|
||||
bankgiro: skattekontoPayment.bankgiro,
|
||||
date: formatDate(skattekontoPayment.due),
|
||||
})
|
||||
}
|
||||
count={1}
|
||||
badge={
|
||||
<span className="text-xs tabular-nums text-muted-foreground">
|
||||
{formatCurrency(skattekontoPayment.amount)}
|
||||
</span>
|
||||
}
|
||||
/>
|
||||
)}
|
||||
{expensePayouts.map((p) => (
|
||||
<WorklistRow
|
||||
key={p.key}
|
||||
|
||||
Reference in New Issue
Block a user