In Entwicklung
Sicherheit
- No duplicate scheduled invoices: scheduled invoices are now claimed atomically before sending, so an overlapping run of the every-5-minute send job can never email the same invoice to a client twice. A send that fails is automatically retried on the next run, and every scheduled send is now recorded in the compliance ledger with its PDF — exactly like a manual send.
Hinzugefügt
- Swiss QR invoice guides: three new German guides explain the QR invoice (
/ratgeber/qr-rechnung-schweiz), the difference between IBAN and QR-IBAN (/ratgeber/qr-iban-vs-iban-schweiz), and how free QR invoice generator options compare (/ratgeber/bester-qr-rechnung-generator-schweiz). The free QR generator page links to all three. - Expanded QR generator FAQ: the free QR invoice generator now answers 11 frequently asked questions (up from 3) in all four languages — including whether data is stored, account requirements, QR-IBAN support, and how the QR invoice replaced the old payment slips.
- AI search visibility:
robots.txtnow explicitly welcomes AI search and citation crawlers (ChatGPT, Claude, Perplexity) on public pages while keeping private app areas blocked and opting out of model training (Content-Signal: search=yes, ai-input=yes, ai-train=no). A newllms.txtgives AI systems a concise, canonical description of Slonge Billing and the free QR invoice generator.
Behoben
- French and Italian QR generator pages no longer repeat "| Slonge Billing" twice in the browser-tab title.
- The QR generator page no longer emits duplicate WebApplication structured data; it now ships one localized WebApplication entry plus new breadcrumb and how-to structured data for search engines.
Hinzugefügt
- French and Italian documentation for the Calendar feature.
Geändert
- Localized landing-page URLs: the free Swiss QR-invoice generator now has French (
/fr/creer-facture-qr-suisse) and Italian (/it/creare-fattura-qr-svizzera) URLs instead of reusing the German address. Old links redirect automatically, and the language switcher, sitemap, and hreflang tags all point to the right per-locale URL.
Sicherheit
- Encrypted calendar tokens at rest: Google Calendar OAuth access and refresh tokens are now encrypted in the database (AES-256-GCM) instead of stored in plaintext, so a database compromise can no longer expose live calendar credentials. Tokens are only ever decrypted in memory at the moment they're used.
Geändert
- Clearer "calendar not set up" message: If Google Calendar integration isn't configured, clicking Connect now returns a clear "Google Calendar isn't configured yet" message instead of bouncing you to a confusing Google error page.
Behoben
- AI account suggestion when marking an invoice as paid: Clicking ✨ AI-Vorschlag in the "mark invoice as paid" dialog now reliably recommends a revenue account instead of often returning "Keine passende Kontoempfehlung gefunden". The request was sending an invalid booking type, which nudged the AI toward a bank-to-receivable entry that has no revenue line for the dialog to use. When a suggestion still can't be applied (for example, the AI proposes a revenue account your chart doesn't contain), the dialog now logs the reason and falls back to the standard accounts so you're never blocked.
Hinzugefügt
- CRM activity timeline: Companies and contacts now have an activity timeline — log notes, calls, tasks, and meetings (with start/end time, location, and participants) against a record. Contacts get a dedicated detail page, reachable from the contacts list and the new Kontakte entry in the navigation. Activities use a flexible association model, so a single entry can be linked to clients, contacts, leads, opportunities, projects, invoices, quotes, or vendor bills.
- Sales opportunities: Qualified deals are now tracked as opportunities (stage, value, probability, expected close) alongside leads, including won → project conversion.
- Calendar import: Import meetings from Google Calendar (live sync) and
.icsfiles (Outlook/Apple export). Eligible meetings land on the CRM timeline, are matched to the right company or contact, and billable ones convert to an unbilled time entry in one click — hours taken from the actual meeting duration. Recurring series are expanded DST-correctly; declined, internal-only, and solo meetings are imported non-billable. Optional AI suggests billability and the likely client for ambiguous meetings. Available in the dashboard (Settings → Calendar, Calendar → Review) and via the CLI/MCP (slonge calendar import|sync|review). Attendee data is kept privacy-aware: unmatched attendees stay raw and are never auto-promoted to contacts, and disconnecting a calendar purges its imported participant data. - In the Review queue, meetings with no automatic match now offer a Suggest with AI action that proposes the likely client, whether it's billable, and a confidence score; once a meeting has been turned into a time entry it's marked Recorded as time entry and can't be converted twice.
Geändert
- Features page previews: The sections on the public Features page now show real product screenshots — invoicing, AI receipt capture, cash-flow forecast, chart of accounts, client management, and the dashboard — instead of placeholder graphics.
- Clearer sidebar icons: Accounting, customer, project, and CRM menu entries (e.g. *Journal*, *Chart of accounts*, *Balance sheet*, *Income statement*, *VAT returns*, *Year-end closing*, *Companies*, *Contacts*, *Leads*, *Pipeline*, *Week view*, *Quotes*) now each have a distinct icon instead of sharing a handful of generic ones.
Behoben
- Paid invoices now reliably appear in the balance sheet and income statement: When marking an invoice as paid, the payment booking could end up with the same account on both sides (e.g. *Bank* against *Bank*). Such an entry is balanced but nets to zero, so the turnover never reached the income statement and the cash never reached the balance sheet. The payment dialog now refuses a booking where the revenue and payment account are identical, and the revenue side must be an actual revenue-type account — so the sale is always recorded where you expect it.
- Create invoice no longer "softlocks" after selecting a customer: On the new-invoice page, clicking Create before choosing a customer showed a warning — but after selecting the customer the warning could persist and block submission. Validation now runs in one place with a single clear message that scrolls into view, instead of relying on the browser's generic field prompts.
Geändert
- Marketing homepage: The hero section now shows a real screenshot of the product dashboard (business overview, cash-flow chart, and open invoices) in place of the previous placeholder.
- Sitemap: The published sitemap (
/sitemap.xml) now lists every public page across all four languages — marketing pages, the Swiss QR-invoice landing pages, the full documentation, the changelog, and the legal pages — so search engines can discover and index the whole site.
Behoben
- Localized documentation: Opening the documentation home in English, French, or Italian (
/docs-en,/docs-fr,/docs-it) no longer shows a "page not found" — it now opens the first article, with the full localized section navigation in the sidebar.
Hinzugefügt
- Multi-language (DE / EN / FR / IT): The entire platform is now available in four languages — German, English, French (Switzerland), and Italian (Switzerland). The language is chosen via the language selector and stored per user (cookie/
localStorage), including automatic browser-language detection. Translated are the entire app (all dashboard pages, forms, tables, status, success, and error messages), transactional emails (including dunning reminders), PDF/document templates, the public website (withhreflangalternates and localized SEO/JSON-LD metadata), as well as the knowledge base and the help chatbot. Numbers, amounts, and dates are formatted per language according to Swiss conventions (e.g.CHF 1'234.50). - _Note:_ Regulated and legal texts (Swiss QR-Bill, debt-collection/SchKG dunning levels, VAT/tax terms, legal pages) were translated using official multilingual terminology and are ready for legal sign-off before going live.
Behoben
- Receipt scan: restaurant receipts were incorrectly assigned the reduced VAT rate (2.6 %): The receipt OCR prompt applied the reduced rate across the board for "Food/restaurants". Swiss VAT, however, distinguishes: 8.1 % for restaurant and café consumption on-site, 2.6 % only for groceries to go (supermarket). The prompt now uses the real VAT codes (
CH_NORM_8_1,CH_REDUCED_2_6,CH_SPECIAL_3_8) instead of the made-upVM77/VM81/VM26and primarily reads the VAT rate printed on the receipt.
Hinzugefügt
- Booked status on the invoice timeline: The status timeline at the top of an invoice now shows the new Booked step after Paid, which turns green as soon as journal entries exist for the invoice. This makes it possible to see at a glance whether a paid invoice has been recorded in the accounting.
- Prepaid timeline: Already-paid invoices (e.g. PayPal/TWINT) now also get a two-step timeline (Paid → Booked) instead of none at all.
Geändert
- Paid invoices appear again in "All" and "Paid": The separate "Paid invoices" tab is gone. Prepaid invoices are listed like regular invoices in the main list and carry the paid/booked badge.
- Paid → Booked badge for all paid invoices: The "Booked" badge, previously only visible for prepaid invoices, is now shown for every paid invoice with journal entries — including standard invoices that were later marked as paid.
Behoben
- Postal-mail PDF/preview showed no invoice number: For the "Postal mail" delivery method, the template header (including invoice number and dates) was hidden to make room for the Swiss letter-envelope layout — but never shown again anywhere. The postal-mail wrapper now renders its own header block with place/date, subject ("Invoice No. RE-2026-XXX"), and due date.
Hinzugefügt
- Paid invoices: Invoices for already-paid orders (e.g. via PayPal) can be recorded directly as paid — without a QR payment slip and without dunning. They appear in their own "Paid invoices" tab and can be created via Record paid invoice as well as via the CLI (
invoice create --paid) and MCP.
Geändert
- Project time entries grouped by month: Within a task, time entries are now grouped by month and can be expanded and collapsed per month. The month header shows total hours and total amount; the current month is expanded when the task is opened.
Hinzugefügt
- Year-end closing: Pre-close checklist with 10 checks, automatic closing entries (account 2990), period lock with reopening (max. 5×/year), trustee bundle (PDF folder always; AbaConnect XML, CSV, receipts ZIP optional). CLI:
slonge jahresabschluss {list,check,close,download,reopen}. MCP tools with a 24h cooldown on closing/reopening. - VAT quarter recording: New page under Accounting → VAT statements to log submitted ESTV statements.
- Background job system (internal): DB-based job queue with cron drain.
Geändert
- Booking lock for closed periods: Journal, invoice, expense, vendor-bill, and credit-note entries dated into a closed period are rejected with HTTP 409.
- Stripe webhook: Payments that fall into a closed period are quarantined with a notification to tenant admins (no booking, no retry loop).
Behoben
- Registration & several Settings-touching endpoints stopped working on prod because the prod DB was missing schema added by migrations between 2026-02-27 and 2026-05-16 (
_prisma_migrationswas stuck behind old failed rows, soprisma migrate deployrefused to apply newer ones; the docker-entrypoint.sh fallback only covered some). Specifically:ComplianceEvent/DocumentArtifacttables,Settings.attachUblXmlOnSend,AuditLog.tokenId,Client.buyerReference. Hotfix applied directly viaops/hotfix/2026-05-18-apply-missing-prod-schema.sql;docker-entrypoint.shextended with idempotent fallbacks so future container starts re-establish them. Migration-table cleanup deferred to a separate session. - Registration error surface: failed signups no longer show a generic "Ein Fehler ist aufgetreten" with nothing for the user or operator to act on. The API now returns a short error code, maps known Prisma failures (P2002 → "Konto existiert bereits", P2022 → "Schema nicht aktuell") to specific messages, and writes a structured pino log entry with the full stack — so the next time something breaks, it surfaces immediately instead of needing prod log archaeology.
- Registration email-send failure no longer silent: if the verification email fails to deliver, the API returns
{ success: true, emailSent: false }and the success screen shows an amber state with a one-click "Bestätigungs-E-Mail erneut senden" button instead of telling the user to check an inbox that will never get the email.
Geändert
- Verification email now uses the platform's
BaseTemplate(consistent logo, header, footer, branding) instead of the legacy inlineReact.createElementcomponent, which rendered as a washed-out full-width orange-button mess in dark-mode email clients. Same German/English/French/Italian copy, properly framed.
Hinzugefügt
- Runtime Peppol critical-check validation for UBL exports: every generated UBL XML (dashboard download, CLI/MCP, auto-attach on send) is now checked against ~40
SLONGE-CHECK-*rules covering EN 16931, Peppol BIS Billing 3.0, and Swiss specifics — IBAN mod-97, QR-IBAN consistency, the closed Swiss VAT rate set, Swiss UID format, ISO 3166 country codes, line and per-VAT-bucket totals math. The invoice detail page shows a green „Kritische Peppol-Prüfungen bestanden" badge when clean, a red expandable issue list when not. Failed validation now disables the primary download — overrides are a deliberate secondary action, role-gated to Buchhaltung / Administrator:in, with a confirmation dialog. Each override is recorded in the hash-chained compliance ledger as a distinctinvoice.ubl_validation_overriddenevent (separate from the existinginvoice.ubl_generated), and the auto-attach pipeline recordsinvoice.ubl_validation_failedwhen it falls back to PDF-only. CLI gainsslonge invoice ubl-validatefor CI-gated pre-checks and a--forceflag for explicit overrides; new MCP toolinvoice_ubl_validatelets agents audit before they send (force-download is deliberately NOT an MCP tool — agents shouldn't bypass validation autonomously). Client.buyerReference(BT-10) — optional buyer-reference field on Client (often a PO number or contract ID). Some Swiss cantonal procurement portals require it on inbound Peppol invoices; the builder emitscbc:BuyerReferencewhen set, andSLONGE-CHECK-META-05surfaces a warning when it's missing.
Geändert
buildInvoiceUbl()validates by default: every call site now getsSLONGE-CHECKvalidation upfront and throwsUblValidationErroron critical rule failures. Opt out with{ validate: false }when a caller wants the bytes regardless. The currency check (CHF-only) moves from the builder'sUblBuildErrorinto the validator (SLONGE-CHECK-CURRENCY-01) — single source of truth.- DRY refactor: extracted the per-VAT-category bucket and totals math (
computeInvoiceTotals) from the UBL builder intosrc/lib/e-invoice/totals.ts. Builder consumes the helper, validator uses it to verify round-trip consistency. Slice 1 fixtures stay byte-identical. @slonge/agent-sdkowns theValidationIssueZod schema (packages/agent-sdk/src/schemas/peppol-validation.ts). The lib-side validator imports the TS type — single public contract, no drift between the API surface and lib internals. Rule-ID regex^SLONGE-CHECK-[A-Z]+-\d{2}$enforced at the schema layer prevents emitting official Peppol BR-* IDs.- The validator covers ~40 critical input-level rules, not the full Peppol BIS 3.0 Schematron set (~150 rules), and does not do UBL 2.1 XSD structural validation. The UI says "kritische Peppol-Prüfungen bestanden" — never "Peppol-valid". Full Schematron parity (Slice 4b) is gated on a Peppol Access Point partner being contracted; until then, customers reporting a recipient-side rejection can escalate and we'll add the specific rule manually.
Hinzugefügt
- Auto-attach Peppol UBL XML to invoice emails (opt-in): a new Settings → Rechnungseinstellungen checkbox (
attachUblXmlOnSend, default off) causes every outbound CHF invoice email to include the Peppol BIS Billing 3.0 UBL XML as a second attachment alongside the PDF. Recipients on B2G procurement platforms (federal administration, cantons) or with e-invoice-aware accounting software (Bexio, Abacus, SAP, etc.) can ingest the structured XML directly — no manual download + forward step. Non-CHF invoices and UBL build failures fall back silently to PDF-only (a successful send takes precedence over a perfect attachment). Each auto-attached export records aDocumentArtifact(kind:invoice_xml_ubl_sent) and aninvoice.ubl_generatedcompliance event, taggedgeneratedFrom: "lib/invoice-send"to distinguish from dashboard / CLI downloads. The toggle is also available via the CLI/MCPsettings_updatetool, and theslonge invoice sendresponse envelope surfacesublSha256+ublByteSizewhen UBL was attached so agentic callers can verify what shipped.
Geändert
- DRY refactor: extracted the shared Prisma → UBL mapping (
mapInvoiceToUblInput+resolveSupplierIban) from the dashboard + CLI download routes intosrc/lib/e-invoice/ubl-mapper.ts. Slice 2 reuses it; the existing route behavior is byte-identical.
Hinzugefügt
- Peppol BIS Billing 3.0 UBL XML export: every CHF invoice can now be exported as a Peppol-conformant UBL 2.1 XML file from the invoice detail page ("E-Rechnung exportieren" card →
GET /api/invoices/[id]/ubl), the CLI (slonge invoice ubl -o), and the MCP server (invoice_ubltool). The XML carries the Swiss QR reference and payment IBAN incac:PaymentMeans, ready to hand to a Peppol Access Point or pass into accounting software (cantonal eInvoicing platforms, EN 16931, etc.). Each download is registered as aDocumentArtifactwith a SHA-256 digest and records aninvoice.ubl_generatedcompliance event in the per-tenant hash-chained ledger. CHF only in this slice; runtime Peppol Schematron validation and Peppol Access Point delivery land in follow-up slices.
Behoben
- Compliance ledger now covers secondary expense and vendor-bill mutation surfaces: cross-cutting review of Phase 1.5b found that the expense approve/reject endpoints (
POSTandDELETE /api/expenses/[id]/approve), the Kreditorenprozess status workflow (PUT /api/expenses/[id]/status), and the vendor-bill approve endpoint (POST /api/vendor-bills/[id]/approve) were mutating financially-relevant status without writing to theComplianceEventledger. They now firerecordExpenseUpdatedEvent/recordVendorBillUpdatedEventso an auditor can trace approve → freigegeben → bezahlt and PENDING → APPROVED / SCHEDULED transitions through the hash-chained ledger like every other mutation. quote.sentledger entries no longer carryinternalNotes:recordQuoteSentEventnow strips the internal-onlyinternalNotesfield from the outbound-communication event payload, matching the metadata hygiene of the other entity helpers.- Distinct
quote.acceptedcompliance event: when a quote status transitions toACCEPTED(via dashboard PATCH or CLI PATCH), the ledger now records both the genericquote.updatedevent and a dedicatedquote.acceptedevent. Previously therecordQuoteAcceptedEventhelper existed but had no production call sites, so auditors couldn't distinguish acceptance from any other update.
Hinzugefügt
- Compliance ledger covers journal entries, credit notes, vendor bills, expenses, and quotes: the hash-chained
ComplianceEventtable now records lifecycle events for every financially-relevant entity, not just invoices. Each entity has dedicated per-action helpers insrc/lib/compliance/{entity}-events.ts(e.g.,recordJournalEntryCreatedEvent,recordCreditNoteCreatedFromInvoiceEvent,recordQuoteConvertedEvent). Compliance dossier exports automatically include the new event types — auditors can verify the full chain of financial state changes from a single ZIP. A new test (src/lib/compliance/archive.test.ts) locks in the all-6-entity-types completeness.
Sicherheit
- Unified audit trail for CLI & MCP: Every write made via the slonge CLI,
@slonge/mcp-server, or the streamable HTTP/api/mcptransport now produces anAuditLogrow alongside the existingApiTokenUsagerequest-envelope record. Covers create/update/delete on clients, projects, invoices, quotes, time entries, expenses, settings, and API tokens — plus the higher-level actions invoice/quote send, quote→invoice convert, and dunning runs. A newAuditLog.tokenIdcolumn attributes each change to the specific API token that initiated it (dashboard mutations leave the column null). PATCH endpoints skip writing an audit row when no tracked fields actually changed.
Behoben
- API token "Revoke" action now visible as a button: On Settings → API Tokens the revoke action per token row was rendered merely as red text without a button frame. The action was clickable but not recognizable as a button — so administrators effectively could not revoke tokens. Switched to the project-wide
Hinzugefügt
- Compliance dossier: Administrators can export audit-supporting records with event hashes, document checksums, and a manifest. Every invoice create/update/delete/schedule and every sent PDF is now recorded in a per-tenant hash-chained
ComplianceEventledger (viasrc/lib/compliance/invoice-events.ts). Sent invoice PDFs are also registered as tamper-evidentDocumentArtifactrows with SHA-256 digests (src/lib/compliance/artifacts.ts). Recording happens on both the dashboard and the CLI/MCP surface so agent-driven changes are auditable too. The full ledger + artifacts are now included in tenant backup ZIPs (compliance/events.json,compliance/document-artifacts.json). - CLI/MCP — Wave 6:
settings_update(CLI:slonge settings update),quote_pdf(slonge quote pdf),quote_send(slonge quote send) — completes the v1 tool surface. - Streamable HTTP MCP transport at
/api/mcp— connect claude.ai / ChatGPT / any remote MCP client without installing the stdio binary. Same bearer-token auth as/api/cli/*. - npm packages:
@slonge/cli,@slonge/agent-sdk,@slonge/mcp-serverto be published publicly at0.2.0. Install withnpm install -g @slonge/clionce released. - CLI/MCP Wave 5 — dunning + report + settings_get. Closes out the v1 CLI/MCP surface per the spec. 6 new MCP tools (
dunning_list_pending,dunning_get,dunning_run,report_list,report_export,settings_get). 6 new API routes. CLI gainsslonge dunning list|status|run,slonge report list|export -o, andslonge settings show. Binary exports (Abacus AbaConnect XML, Abacus ASCII.asr) ride the JSON envelope ascontentBase64and the CLI base64-decodes them when-ois given. - CLI/MCP Wave 4 — quote + quote-convert. Full CRUD for quotes via the CLI and the MCP server, plus the
quote_converttool that turns an accepted quote into a draft invoice. Convert pipeline extracted tosrc/lib/quote-convert.tsand shared with the dashboard route (behavior byte-identical for the dashboard caller). CLIquote createaccepts line items as a--items-jsonarray; quote-level VAT falls back tosettings.defaultVatRate. 6 new MCP tools (quote_list,quote_get,quote_create,quote_update,quote_delete,quote_convert), 4 new API routes. - CLI/MCP Wave 3 — time-entry + expense + receipt OCR. Full CRUD for time entries and expenses via the CLI and the MCP server (11 new MCP tools, 7 new API routes). Time-entry
createaccepts--project-id(auto-creates the project's "Default" story) or--story-id. Quick aliasslonge time-entry log --project-id --hoursdefaults the date to today. expense upload/expense_upload— first AI-quota-gated CLI/MCP tool. Submit a receipt image or PDF (base64, max 6 MB), get back parsed amount/vendor/date/description plus Swiss accounting suggestions (account number + VAT code). Counts toward the tenant's monthlyaiCallsPerMonthquota; returns403 FORBIDDENwhen the plan doesn't include AI,429 QUOTA_EXCEEDEDwhen the cap is reached. v1 returns OCR data only — receipt persistence to disk/S3 is deferred to a follow-up PR.POST /api/cli/invoice/[id]/send— CLIslonge invoice sendand theinvoice_sendMCP tool can now actually send invoices via the API (previously returned 404). Shares the dashboard's full pipeline — PDF generation, Swiss QR-bill, React Email template, eligibility checks, Resend delivery, automatic draft → sent status flip — via the newsrc/lib/invoice-send.tsmodule.Project.budgetcolumn — CLI/MCP--budgetvalues now persist instead of being silently dropped. Database migration20260514120000_add_project_budgetadds the nullable column; entrypoint script auto-heals existing deployments on container start.- API & MCP documentation page (DE + EN) at
/docs/api-mcpwith quick start, tool overview, error codes, and security best practices. New "API & MCP" section in the docs navigation; the chatbot now also understands CLI/MCP questions. - API tokens for slonge-billing CLI and MCP server. Manage tokens at Settings → API Tokens (admin only). Tokens use Bearer auth (
Authorization: Bearer slk_*) and work against staging and production. Each request is rate-limited (60/min) and audit-logged. @slonge/agent-sdkworkspace package — Zod schemas + HTTP client, single source of truth for CLI, MCP server, and Next.js route validation.@slonge/mcp-serverworkspace package — stdio MCP server exposing ~22 tools (client/project/invoice CRUD, invoice send/mark-paid, API token CRUD) for Claude Desktop, Cursor, Claude Code.- CLI invoice send + mark-paid subcommands; global
--json,--verbose,--dry-runflags; realtest:all/test:fullcommands wired to workspace scripts.
Geändert
- Quote PDF generation extracted to
src/lib/quote-pdf.ts; dashboard route now delegates and returnsapplication/pdf(previously returned a JSON envelope with rendered HTML). - Quote send pipeline extracted to
src/lib/quote-send.ts(mirrorssrc/lib/invoice-send.ts). Dashboard send route now attaches the quote PDF to the outgoing email. src/app/api/ai/receipt/route.tsinternals refactored — the OCR pipeline (plan gate, monthly quota check, OpenAI call, account/category resolution,UsageRecordwrite) lives in the newsrc/lib/receipt-ocr.ts. The dashboard route's response shape is unchanged.src/app/api/quotes/[id]/convert-to-invoice/route.tsinternals refactored — the convert pipeline (find-or-create project, atomic invoice + material costs creation, quote status flip, settings increment) lives in the newsrc/lib/quote-convert.ts. The dashboard route's response shape is unchanged.- Dunning processor refactor —
src/app/api/dunning/process/route.ts(the cron entry point) now delegates each tenant's run tosrc/lib/dunning-run.ts. Behavior byte-identical for the cron caller; the CLI/MCP/api/cli/dunning/runroute calls the same lib with a single tenant id. - Report exporters split into shared libs —
src/lib/reports/{balance-sheet,income-statement,vat-summary,abacus-xml,asr-ascii}.ts. Dashboard routes refactored to thin shims; response shapes preserved byte-identical. - Dunning email now matches the invoice email: Dunning reminders are sent in the same layout as invoices — header, line-item list, Swiss QR-Bill in the email body, and a PDF attachment. The previous "View invoice" button linking to a login-protected page was removed; the PDF attachment is the canonical version the customer keeps. The dunning salutation with level, days overdue, and deadline is shown as accompanying text above the invoice.
- CLI authentication:
~/.slonge/config.jsonnow usesapiTokenfield (Bearer). Legacysecretfield still works on staging withENABLE_CLI_API=truebut prints a deprecation notice; will be removed 2026-11-11. slonge invoice create --descriptionis now required (matches server validation). Previous CLI made it optional and always 400'd.- Existing
/api/cli/*routes now validate request bodies against shared Zod schemas from@slonge/agent-sdk. /api/cli/invoicelist and single-invoice routes now scope tenant by client (always required) instead of project (nullable), so invoices created without a linked project are visible to CLI/MCP callers.- Quantity input: steps depend on the unit: The up/down arrow keys in the quantity field of an invoice or quote line item now increment by 1 for piece, day, and flat rate, by 0.1 for hour (the typical billing granularity for hourly work), and by 0.01 for meter and kilogram. Applies on the New invoice, Edit invoice, New quote, and Edit quote pages.
Behoben
- Dunning fees and default interest in preview, print, and QR-Bill: As soon as an invoice has been dunned, the print view, the attached PDF, and the on-screen preview now show three additional lines — Invoice amount, Dunning fees, and Default interest — and the Total amount as well as the QR-code amount match the current outstanding debt. Previously all three showed only the original invoice amount.
- "Schedule sending" now actually sends invoices: The cron endpoint
/api/invoices/process-scheduled(and the daily dunning endpoint/api/dunning/process) were not being called by any scheduler — the old KubernetesCronJobmanifests underops/k8s/jobs/were never deployed (production runs on a single Docker VM, not on Kubernetes). Set up as a hostcronon85.217.161.119via the new [ops/host-cron/](ops/host-cron/) setup script. Scheduled invoices are now processed every 5 minutes, the daily dunning run at 07:00 UTC. _Prerequisite: the setup script was run once on the VM — seeops/host-cron/README.md._ - Postal-mail layout: QR code on a second page for long invoices: With too many line items, the middle section of the postal-mail invoice grew into the lower A4 third and overlapped the QR payment part. The layout now switches to natural flow with
break-inside: avoidon the QR area — for short invoices the QR still sits on the lower half of the page, for long ones it breaks onto a second page. - Swiss cross missing in the postal-mail QR: The dunning and invoice PDFs of the postal-mail variant no longer displayed the mandatory black square with the white Swiss cross at the center of the QR code — causing the QR code to be rejected by many Swiss banking apps. The overlay is now drawn with pure HTML/CSS (instead of an SVG data URI) and renders identically in browser preview, PDF, and print.
- QR code blurry in the postal-mail preview: QR resolution increased from 400 px to 1024 px and
image-rendering: crisp-edgesset — the QR now stays sharp at any scaling ratio.
Sicherheit
- API tokens stored as SHA-256 hash, not plaintext.
- Token creation requires the TENANT_ADMIN role.
- Full token revealed exactly once at creation.
Hinzugefügt
- Documentation overhauled: The public
/docsis back in sync with the app — new Dunning section, chart-of-accounts hierarchy (4-level Swiss SME structure), quick actions (configurable dashboard quick actions), foreign-currency receipts in Smart Inbox + expenses (Frankfurter API auto-fetch), template preview with thumbnails, notifications section, and Sign in with Google in the first steps. Both DE and EN updated; chatbot capabilities extended withdunning,smart-inbox, andai-features. - Help chatbot moved to the documentation: The floating help assistant now lives on
/docs(and/docs-en) instead of on every authenticated app page. Same RAG-based functionality, less visual noise in day-to-day work. Sign-in still required. - Automatic CHANGELOG rotation (planned): A new GitHub Actions step is intended to move
## [Unreleased]into a dated entry (## [YYYY-MM-DD] (sha)) after a successful production deploy and commit it back tomain. _Note: Currently temporarily disabled due to a missingOPENAI_API_KEYrepo secret; will be re-enabled once the secret is set._ - Doc-update reminder hook: A PostToolUse hook in
.claude/settings.jsonreminds contributors to updatedocs/de/,docs/en/, andCHANGELOG.mdwhen source files insrc/,packages/, or Prisma migrations are changed. - Products as invoice line items: When creating or editing an invoice, you can use the Choose from products button to add products and services from your catalog as line items with one click — including search, multi-select, and automatic adoption of label, unit, and unit price.
- Send test dunning: Under Settings > Billing there is now a "Send test dunning" card. Admins can use it to send a test dunning reminder of level M1, M2, or M3 to their own or a specified email address — without an overdue invoice, without waiting for the daily cron. Helps validate the template and the Resend configuration before a real dunning run.
- Book foreign currency directly: Expenses in foreign currency (EUR, USD, etc.) can now be booked directly from the Smart Inbox. The CHF rate is fetched automatically from the Frankfurter API if it is not yet stored. The inbox shows the CHF amount (e.g.
≈ CHF 48.50), or a note that the rate will be fetched at booking time. - Automatic dunning (cron): New Kubernetes CronJob
dunning-cronjob.yamlcalls the dunning process daily at 07:00 UTC. Dunning reminders are now sent automatically (automode) or shown for approval (semi_automode).
Geändert
- Line-items API: The
status=billedfilter no longer includes paid entries; usestatus=paidfor paid entries. - PDF attachment now matches the print view: The PDF attached to customer emails is now generated by rendering the same HTML template shown on "Print" in the app — including logo, colors, Swiss QR-Bill, and the full line-item list. Technically: headless Chromium (Playwright) renders the invoice template to PDF instead of the old programmatic PDFKit layout.
- "View invoice online" button removed: The link in invoice emails led to a page that requires a login — not accessible for external recipients. The PDF attachment fully replaces this view.
Behoben
- Create client from the invoice/quote editor: The inline "New" dialog next to the client field could not create a client (error "Error creating client") — the form sent the
addressfield, but the data model expectsaddressLine1. Inline creation now works in both the invoice and the quote editor. - Postal-mail address in the right window: The recipient address for physical delivery now sits on the right of the sheet (left 125 mm, width 80 mm), matching the window of Swiss C5/B5 postal-mail envelopes. Previously it was on the left — which avoided slipping when folding or printing in the wrong position.
- PDF generation in production: The container now installs the Chromium matching
playwright-core(instead of Debian's system Chromium), so PDF sending works reliably in Kubernetes. - PDF attachment when sending invoices: Emails to customers again contain the invoice as a PDF attachment. Cause:
pdfkitwas not registered as an external server package, which made PDF generation fail at runtime and the error was silently swallowed. If PDF generation now fails, the email is no longer sent and an error message appears. - Invoice print across two pages: Normal invoices (email delivery) are no longer split across two pages. The card border and double inner padding were removed for print, A4 margins of 15 mm set, and line breaks in the middle of table rows prevented.
- Project status after payment: The invoice status on the project page now updates automatically when switching from the invoice to the project window — even if the project window was already open.
- Chart-of-accounts account types: Three revenue accounts (financial income, extraordinary income) were incorrectly classified as expense. Both templates corrected.
- Email-to-Action Automation: Forward emails to your personal inbox address and let AI automatically process them into expenses, vendor bills, leads, or documents.
- Personal Inbox Address: Each tenant gets a unique address:
inbox-{company}@inbox.slonge-billing.ch - AI Classification: Incoming emails are analyzed and classified by intent (expense, vendor bill, lead, document).
- Auto-Create Entries: Receipts become expenses, invoices become vendor bills, inquiries become leads.
- Settings UI: Configure which email types to process, auto-approval thresholds, and notification preferences under Settings → Smart Inbox.
- 100% Swiss Hosting: Self-hosted SMTP server on Swiss infrastructure. No third-party email services.
- Haraka SMTP Server: Lightweight Node.js mail server running on ports 25/587 with TLS.
- Webhook Integration: Emails processed via secure webhook with master secret authentication.
- S3 Attachment Storage: Email attachments stored in Swiss Exoscale S3 bucket.
- Visual Template Selector: When creating invoices or quotes, templates now display as a grid with visual thumbnails. Hover to load preview, click for full A4 preview in modal.
- User Template Preferences: Selected template is saved per user. Next time you create an invoice/quote, your preferred template is pre-selected.
- Tenant Default Templates: Admins can set default invoice/quote templates in Settings → Templates.
- Configurable Quick Actions: Dashboard now shows customizable quick action buttons. Click the settings icon to personalize.
- 10 Available Actions: New Expense, Scan Bill, New Invoice, New Quote, New Project, New Client, New Product, New Lead, Time Entry, Journal Entry.
- User Preferences: Select up to 8 actions. First 4 show on mobile. Reorder by dragging up/down.
- Persistent: Your selection is saved to your profile.
- Swiss KMU Kontenplan: Full support for hierarchical account structure (1/10/100/1000 levels for Klasse/Hauptgruppe/Gruppe/Konto).
- Visual Hierarchy: Account list shows indentation and group styling. Groups are not bookable.
- Template Descriptions: All Kontenplan templates now mention their hierarchical structure.
- Consolidated AI Invoice: Removed duplicate "AI Rechnung" button. QuickInvoice (Schnellrechnung) remains as the single AI-powered invoice generator.
- AI Invoice Generator: Create invoices using natural language prompts like "Rechnung für Acme GmbH mit allen unbezahlten Stunden". Opens via button on invoices page. Auto-fetches unbilled time entries and material costs, matches clients/projects with fuzzy search, calculates VAT from settings.
- AI Cash Flow Forecast: 90-day liquidity prediction with confidence bands. Analyzes per-client payment patterns, detects recurring expenses, shows alerts for shortfalls. Dashboard widget with chart. (
GET /api/analytics/cash-flow-forecast) - AI Anomaly Detection: Statistical analysis to detect unusual patterns - expense anomalies (>2.5σ), vendor price increases (>20%), new vendor detection, client payment behavior changes. Dashboard widget with severity indicators.
- AI Project Estimation: Estimate new project costs based on historical data. Input description + complexity → get hours/cost/duration ranges with breakdown by category. Uses AI-enhanced matching when OpenAI configured.
- AI Smart Reminders: Proactive business reminders on dashboard - overdue invoices, due-soon invoices, unbilled time entries, stale drafts, dormant clients, pending vendor bills, cash flow warnings. Priority levels with direct action links.
- AI Email Drafting: Generate professional invoice emails with "AI E-Mail-Entwurf" button. Adapts tone for client relationship (new vs long-term), handles initial/reminder/followup/thank_you types, Swiss German business tone.
- AI Smart Search: Natural language search across all data - "Alle offenen Rechnungen diesen Monat", "Kunde Müller", etc. Understands German/English, parses dates, filters by status. Command palette style UI.
- AI Duplicate Detection: Find potential duplicate invoices, expenses, vendor bills. Uses Levenshtein similarity for text matching, flags 60%+ as potential and 90%+ as likely duplicates.
- AI Features Documentation: Comprehensive API reference at
docs/AI-FEATURES.mdwith endpoints, request/response examples, configuration guide. - E2E Tests: Playwright tests for AI features covering UI components, API responses, and error handling (
e2e/ai-features.spec.ts). - Database Migrations: Added missing VendorBill columns (documentUrl, journalEntryId, paymentReference, etc.) that were causing API errors
- Credit Notes Schema: Added CreditNote and CreditNoteItem tables with proper foreign keys
- Document Templates: Added DocumentTemplate table for customizable invoice/quote templates
- Settings Schema: Added creditNotePrefix, creditNoteNextNumber, and quoteValidityDays columns
- Rate Limit Config: Fixed cashflow API using incorrect rate limit configuration
- Staging Environment: Set up Exoscale SKS staging environment with DBaaS PostgreSQL
Hinzugefügt
- Quotes (Angebote): Create and manage quotes with line items, auto-numbering (AN-2026-001), validity dates, and status workflow (Entwurf → Gesendet → Akzeptiert/Abgelehnt). Convert accepted quotes to invoices with one click.
- Vendor Bills (Lieferantenrechnungen): Track incoming bills from suppliers with line items, approval workflow, payment recording, and PDF attachments. Tabs: Ausstehend, Genehmigt, Überfällig, Bezahlt.
- AI Vendor Bill Scanner: Upload JPG/PNG of invoices (including Swiss QR-bills) to auto-extract vendor, amount, dates. Shows confidence scores and suggests matching existing vendors.
- AI Client Insights: View client analytics including revenue stats, payment behavior rating (früh/pünktlich/verspätet), activity level (aktiv/abkühlend/inaktiv/neu), 12-month revenue chart, and AI-generated insights in German.
- AI Cashflow Forecast: Predict cash flow 30-180 days ahead with confidence bands. Warns of potential liquidity issues. Dashboard widget shows 30-day preview. Export as CSV.
- AI Booking Suggestions: Receipt scanning now suggests expense accounts, VAT codes, and payment accounts for direct booking.
- Dashboard Widgets: Cashflow chart (12-month income vs expenses), pending invoices donut, pending bills, quick actions, recent activity timeline, and getting started checklist (dismissible).
- Top Customers Widget: Shows top 5 clients by revenue with health indicator dots (🟢🟡🔴🔵). Click to navigate to client detail.
- Customizable Dashboard: Toggle widgets on/off via Settings → Dashboard.
- Enhanced Client List: Health indicators per row, quick filters (Top-Kunden, Aktive, Inaktive), sorting by revenue, revenue display in list view.
- Data Import/Export: Export clients, invoices, and other data as CSV with Swiss formatting (DD.MM.YYYY dates, 1'234.56 numbers). Full backup downloads ZIP with all CSVs + receipts. Import wizard supports Bexio CSV format.
- Document Templates: 4 system templates (Modern, Classic, Minimal, Bold) with customizable colors, bank detail visibility, header/footer text. Preview with sample data. Set defaults per document type.
- List Page Tabs & Bulk Actions: All list pages (invoices, expenses, projects) now have tabs with counts, multi-select with bulk actions dropdown, unified search, and helpful empty states with CTAs.
- Reusable List Components: Consistent ListTabs (horizontal scroll on mobile, count badges), BulkActions dropdown, and ListHeader with search/filters across all pages.
- Swiss Export Formatting: All CSV exports use Swiss date format (DD.MM.YYYY), Swiss number format (1'234.56), and UTF-8 BOM for Excel compatibility.
- Google OAuth Login: Sign in or register with Google for faster account setup. Existing users can link their Google account for one-click login.
- Impressum Page: Legal notice page at
/legal/imprintwith multilingual support (DE/FR/IT/EN). - Project Document Import: Upload PDF/DOCX project proposals and let AI extract project details, tasks, and timelines automatically at
/projects/import. - Automatic Client Matching: When importing projects, the system uses fuzzy matching to find and suggest existing clients.
- Public Documentation: Browse all help docs at
/docswith sidebar navigation. - Changelog Page: View all updates at
/changelogwith timeline layout. - English Documentation: Full English docs available at
/docs/en/. - Auto-embed Updates: Documentation embeddings regenerate automatically on deploy.
Geändert
- Direct Booking Default: "Direkt verbuchen" checkbox now defaults to checked when creating expenses.
- Privacy Protection: Sensitive data (emails, phone numbers, IBANs) are sanitized before sending to AI.
- CI workflow now regenerates RAG embeddings when docs change.
- CI workflow now purges Cloudflare cache after successful deployment.
Behoben
- Expense Totals: Foreign currency expenses without CHF conversion now fall back to original amount instead of being excluded from totals.