Zum Hauptinhalt springen

Changelog

Alle Updates, neue Funktionen und Verbesserungen.

Gratis Tool

QR-Einzahlungsschein gratis erstellen

Neue QR-Rechnungs-Features ausprobieren? Mit dem kostenlosen Generator erstellen Sie eine einzelne Schweizer QR-Rechnung ohne Anmeldung.

Zum QR-Generator
In Entwicklung

Hinzugefügt

  • Scan up to 20 receipts in one go: Expenses gained a Scan batch action (/expenses/scan). Drop in up to 20 images or PDFs — 10 MB each, or shoot them with the phone camera — and they are read one after another while you already review the ones that are done. Each finished receipt becomes a card: the original on the left, the editable proposal on the right (description, vendor, amount, currency, date, expense account, VAT code, category) with a confidence badge. Book it, Discard it, or Rescan it, with A / R to decide and J / K to move, so twenty receipts are a minute's work rather than ten. Discarding can be undone for five seconds; Book all clears the rest in one action. Closing the tab is safe — the batch finishes in the background and reopens from Recent imports.
  • **Booking a scanned receipt creates the expense *and* posts it: To be unambiguous about it, because it writes to your ledger: scanning alone changes nothing and creates no expense — a discarded proposal is a genuine no-op. Book** creates the expense with the original attached as a receipt and posts the journal entry (debit the suggested expense account, credit bank 1020, document number EXP-…), exactly as booking from the Smart Inbox already does. If no matching account exists, or a foreign-currency rate cannot be fetched, the expense is still created and the posting is left for you to make by hand.
  • Scan batches follow the same privacy rule as expenses: In a company running the team workflow, employees see only the batches they uploaded themselves — including the uploaded files — while accountants and administrators see all of them. A staged receipt carries the same vendors and amounts the finished expense does, so it is compartmentalized from the moment it is uploaded rather than only once it is booked.
  • A scan batch is refused up front when the AI quota cannot cover it: Every file costs one call against your monthly AI quota, and every rescan one more. The whole batch is reserved when you upload, so a 20-file batch with 5 calls left is refused before a single file is uploaded instead of leaving you with a half-scanned pile. The upload screen states what is left ("384 of 500 scans left this month") and blocks the start when the selection is too big. Only one batch may be in flight per company.
  • Tell the scanner what to look for: A receipt the AI misread can be sent back through with a free-text hint — "the total including VAT is at the bottom right" — per receipt via Rescan in the app, or for a whole batch with --prompt from the CLI and the MCP tools.
  • PDF receipts are now scanned: Receipt scanning accepted images only and rejected PDFs outright, which is the format most supplier invoices actually arrive in. PDFs now work in the bulk scan and in the single-receipt scan: a digital PDF is read from its text (fast, accurate, and no image is sent anywhere), a scanned one has its first page converted to an image and read like a photo. The receipt-upload file picker offers PDFs alongside photos accordingly.
  • Bulk scan from the CLI and MCP: slonge expense scan invoices/*.pdf with --prompt and --approve-all, plus expense scans, scan-status, scan-approve, scan-reject and scan-rescan; AI assistants get the matching expense_scan_* tools. The same plan, quota and role rules apply as in the dashboard — anyone may scan, because scanning only proposes, but approving posts to the ledger and needs the accountant role.
  • Recover the attachments of older Smart Inbox emails: Emails processed before today's fix kept only one attachment, but the original files were never deleted. A Re-attach documents action on each Smart Inbox entry (accountants and administrators) re-runs the selection over the email and attaches whatever is missing to the entry it already created, reporting how many were added. The old mismatched document — the one whose file details described a different attachment than its contents — is replaced rather than left sitting next to the repaired one, so a booking never ends up with two documents and no way to tell which is right. It is idempotent — an attachment that is already there is skipped, never duplicated — and it is also available as POST /api/inbox/{id}/reattach.
  • Rebill expenses to the client: An expense booked against a project can now be charged straight on to the client with the Rebill to client toggle — no more re-typing it as a material cost and losing the receipt. The expense becomes a line on the project's next invoice (1 × Lump sum), and it appears identically on the PDF, the print view, the client email and the UBL e-invoice. A billable amount overrides what the client is charged, for rounding a 187.40 hotel bill up to 190, adding a markup, or billing 0 for something you absorb; left empty, the expense is billed at cost. A rebilled expense is both a cost and revenue in your books — that is correct double entry, not double counting, and the docs now say so.
  • Expenses on the project page: Projects have a Expenses section next to Material, with the same table, inline form, billing-status badges and mobile card rows. Editing and deleting are offered only while the expense is still open.
  • Capture a receipt with the phone camera: Receipt uploads on mobile now offer Take photo beside the file picker, which opens the camera directly. The photo is attached and read by the AI immediately, so amount, vendor and date arrive pre-filled. Desktop is unchanged.
  • VAT liability widget: A new dashboard widget for administrators and accountants shows what is expected to be paid to the FTA for the current VAT period — output VAT, less credit notes, less input VAT — with the period label and the filing deadline (period end + 60 days). It uses the effective reporting method, covers the statutory VAT period rather than the dashboard period, and flips to a refund claim when input VAT is higher. It is a working figure for cash planning, not a substitute for the return you file. Hidden entirely when the tenant is marked not liable for VAT.
  • VAT reporting settings: Settings → Billing gained a VAT reporting card: quarterly (default), half-yearly or yearly reporting period, the read-only effective method, and the not-liable-for-VAT switch.
  • Explain a project's open amount: The Open tile in a project's billing overview now expands into a per-month breakdown — hours and their amount, material, expenses — with a footer that sums to the tile and says so.
  • Billable expenses from the CLI and MCP: slonge expense create/update accept --billable, --no-billable, --billable-amount, --project-id and --clear-project; slonge expense list filters on --billable / --not-billable / --billing-status. Project and invoice reads surface expense positions, and the expense_create / expense_update MCP tools carry the same fields.

Geändert

  • The dashboard period switcher now governs the whole page: The cash-flow chart and the monthly trend charts were pinned to a hard-coded 12 and 6 months, and recent activity was not scoped at all, so switching tabs moved a few small numbers while the charts sat still. Charts now derive their window from the selected period — this month draws 6 trailing months, last 3 months draws 12, this year draws the calendar year, all time draws every month with data up to 36 — and recent activity follows the period too.
  • Every dashboard widget states its timeframe: Each widget now carries a one-line note saying whether it follows the selected period, is a snapshot as of today, or covers its own stated window. Open items, pending invoices and vendor bills, top clients and smart reminders remain deliberately "As of today": an invoice overdue for five months is open today regardless of the tab you picked.
  • Project billing tiles show what they are made of: The subtext under each tile now names the real composition (12.5 h · material CHF 340 · expenses CHF 180) instead of the vague {hours}h + Material — which, as it turns out, never rendered at all.
  • Scheduled invoices send the same positions as interactive ones: The scheduled-send job built its invoice lines from its own copy of the logic. It now uses the shared line builder, so a scheduled email can no longer list a different set of positions than the same invoice sent by hand.

Behoben

  • A forwarded email no longer loses its invoices, and a receipt's file details now match its contents: Smart Inbox kept at most one attachment per email — the first image and the first PDF were the only ones ever considered, and everything else was discarded without a word. Worse, when an email carried both, the PDF's bytes were stored but the receipt's file name, format and size were taken from the image, so a signature logo plus a PDF invoice produced a receipt that claimed to be a small PNG, pointed at the invoice, and rendered as a broken image. Every attachment worth keeping now becomes its own receipt, described by its own file. Inline images from the message body (signature logos, dividers, tracking pixels) and images under 20 KB are left out, all PDFs are kept when there is one, images only when there is none, and at most ten per email — anything beyond that is recorded on the email rather than dropped silently. An attachment that is too large or in an unsupported format now fails on its own, with the reason on the email, instead of taking the rest of the message down with it. Reading the email with AI still costs exactly what it did: only one attachment is sent to the model.
  • A suggested account that is not an expense account is no longer posted: When booking an expense from the Smart Inbox, the account number the AI proposed was looked up by number alone. Account numbers are unique across your whole chart, so a suggestion of "1020" resolved to the bank account — which is also the credit side of the entry — and produced a balanced but entirely self-cancelling posting that nothing downstream would flag. Only an active, bookable expense account is accepted now; anything else leaves the expense created and unposted, for you to book by hand.
  • Receipt-scanning messages now appear in your language: Five messages from the receipt scanner — quota exhausted, AI not included in your plan, service unavailable and the two read failures — were written in German in the code and were shown in German to English, French and Italian users too.
  • Scheduled positions were missing from every project billing tile: When an invoice's send was scheduled, its time entries and material costs moved to a scheduled state that the project billing summary did not know about. Those positions fell out of all four tiles and out of the progress-bar total, so a project's figures silently failed to add up to its own value. There is now a Scheduled tile, a fourth progress-bar segment, and the total includes it.
  • A billed expense can no longer be rewritten: Description, amount, currency, CHF conversion, billable amount, date and project assignment are frozen once an expense sits on an invoice, and it can no longer be deleted — the same protection invoiced time entries already have, for the same reason: those fields are printed on an issued document. Correct them with a credit note instead.
  • A foreign-currency expense can no longer be rebilled without a conversion: An expense in a currency other than the project's, with no CHF equivalent recorded, can neither be marked billable nor attached to an invoice. Billing a EUR figure as CHF is worse than refusing.
  • Marking an invoice paid now settles its rebilled expenses too: Recording a payment moved the invoice's time entries and material costs to Paid but left the rebilled expenses sitting at Billed, so a fully paid project still showed an outstanding expense balance.
  • Editing an expense's amount, currency or date no longer keeps the old CHF conversion: The conversion belongs to one amount-currency-date combination, and changing any of them left the previous CHF figure in place. Since that figure is what a rebilled expense is charged at, it is now cleared and has to be recorded again before the expense can be rebilled.
  • A full credit note now reverses the rebilled expenses too: A credit note created from an invoice listed only its time entries and material costs, so cancelling an invoice that carried rebilled expenses reversed less than the invoice was worth. Expenses now appear in the selection list and are credited with everything else.
  • Rebilled expenses on a foreign-currency invoice are charged in the right currency: An expense was priced at its stored CHF conversion even when the project bills in EUR or USD, so a single invoice mixed EUR service lines with CHF-valued expense lines. An expense already booked in the project's currency is now billed at cost, the CHF conversion is used only when the invoice is actually issued in CHF, and an expense in a third currency — with no figure in the project's currency at all — is refused rather than charged at a meaningless number.
  • A rejected expense can no longer be charged to the client: Rejecting an expense left its Rebill to client flag set, so a receipt that had just been refused internally stayed in the project's open positions and could still land on an invoice. Rejection now clears the flag, and invoice creation refuses a rejected expense outright.
  • Expenses on a project are no longer visible to colleagues in team mode: A team-mode employee sees only the expenses they recorded themselves, but the project's positions, open items and billing overview returned every expense on the project — including other people's vendors, notes and amounts. All three now apply the same restriction as the expenses list.
  • Internal expense notes are no longer printed on the client's invoice: The Notes field on an expense is the internal remark on your own supplier bill, but it was being rendered under the expense's line on the invoice PDF, print view, client email and e-invoice.
  • Rebilled expenses now appear on the e-invoice exported from the CLI and MCP tools: The UBL export offered through slonge and the AI assistant tools omitted rebilled expenses, so the e-invoice it produced billed less than the invoice itself. The reminder email had the same gap: it itemized only time and material while showing the full subtotal.
  • A rebilled expense can no longer be moved to another company's project: The expense API accepted a project ID from the request without checking it belonged to your company, which could attach an expense to a stranger's project. The same check now applies to expense categories.
  • A billed expense can no longer be changed or deleted by a request already in flight: The billing checks on updating and deleting an expense read the record first and wrote afterwards, so an invoice being created in that split second could claim the expense and still have it rewritten or removed underneath. Both writes now re-check the billing state as they happen, and the change is refused with a "reload" message instead.

Sicherheit

  • Invoiced time entries are now immutable: The hourly rate of an invoiced time entry was already protected, but its date, hours, task and note could still be changed. An invoice builds its lines from the time entries it bills — hours and rate make the amount, the task becomes the line description, and the note becomes the line note printed on the document — so editing any of them silently rewrote an already-issued invoice the next time it was rendered or re-sent. All of them are now refused once the entry is billed, paid, or attached to an invoice, and Edit is no longer offered on those entries. To correct an issued invoice, use a credit note.

Hinzugefügt

  • Change a project's hourly rate: A project's rate could only be set when the project was created — a contract rate change mid-project had no home in the app. The Hourly rate tile on a project now has a Change rate action. Enter the new rate and optionally re-price hours that are already logged but not yet invoiced, bounded by an Effective from date, so a contract that switches mid-project leaves earlier hours at the old rate. A preview shows how many entries are affected and how the project value changes before you confirm. Hours that already sit on an invoice are never re-priced.
  • Per-entry hourly rate: The rate is now editable on an individual time entry while it is still unbilled, for one-off exceptions. Entries whose rate differs from the project rate show it next to the amount.
  • Rate changes from the CLI and MCP: slonge project change-rate --hourly-rate 145 --reprice-unbilled --effective-from 2026-08-01, and the matching project_change_rate tool for AI assistants.

Behoben

  • Failed time-entry edits are no longer silent: Saving a change to a time entry ignored the result, so a rejected edit looked like it had been applied until the row refreshed. Failures are now reported.

Sicherheit

  • The hourly rate of an invoiced time entry can no longer be changed: The time-entry API accepted a new rate regardless of billing status, so an entry already on an invoice could be re-priced and leave that invoice's total disagreeing with its own line items. The rate is now rejected once the entry is billed, paid, or attached to an invoice — enforced by the database write itself, so an invoice being issued at the same moment cannot slip past the check.
  • Rate changes are serialized against invoicing: Re-pricing a project's open hours now runs at the same isolation level as marking an invoice paid. If the two collide, the rate change is refused with a retry message instead of writing a figure that does not match what was billed.
  • An invoice can no longer be issued at a price that changed while it was being created: Creating an invoice read the hours and rates of the selected positions, computed the total, and then claimed those positions by ID only. If a rate change landed in that window, the positions were attached anyway — the invoice stored the old total while its own line items rendered the new rate, so the document contradicted itself. Creation now re-checks that each position still has the exact hours and price it was quoted at, and is refused with a "positions changed, please reload" message otherwise.

Behoben

  • The position picker no longer jumps while a month loads: Switching months showed a single line of text that was then replaced by the list of items, so the dialog visibly jumped. It now shows placeholder rows shaped like the final content.
  • No stale item count while switching months: The Add positions button kept showing the previous month's count (for example "Add 3 positions") until the new month finished loading. It no longer shows a count until the items on screen belong to the selected month.

Behoben

  • Open positions that fail to load no longer look like an empty month: When the open positions of a project or a selected month could not be loaded, the position picker showed "no open items for this month" — indistinguishable from a month with genuinely nothing to bill, so work could be left uninvoiced. It now states that loading failed and offers a retry.

Hinzugefügt

  • Invoice a single month from a project: The Create invoice button in a project's billing overview now has a month selector next to it. Bill all open items as before, or pick one month to invoice only that month's time entries and material costs — the invoice wizard opens pre-filtered, and you can still switch months or deselect items there.

Behoben

  • Closing accounts no longer offered as opening balances: Buchhaltung > Anfangssaldo listed technical closing accounts (class 9 — Eröffnungsbilanzkonto, Erfolgsrechnung, Bilanz) under Eigenkapital whenever a chart of accounts had them typed as equity. Booking an opening balance into the Eröffnungsbilanzkonto is circular, since that account is the counter-entry of the opening booking itself. These accounts are now excluded, both from the account list and from the server-side validation.
  • Account type suggestion for cost classes: The helper that proposes an account type from its number classified classes 4 (Material- und Warenaufwand) and 5 (Personalaufwand) as revenue instead of expense.

Behoben

  • Canonical marketing redirects: Historical QR-invoice URLs, /en/home, and the www hostname now permanently redirect to their canonical pages. Redirect-only aliases are no longer advertised in the sitemap, improving Google crawl and indexing signals.

Hinzugefügt

  • Dashboard period selector: The dashboard now has a This month / Last 3 months / This year / All time switch, and every figure states the timeframe it covers. Revenue and cost figures follow the selection; Open items stay a snapshot as of today and say so. Your choice is remembered between visits.
  • Skip any onboarding step: Every step of the setup interview can now be skipped, individually or all at once, and skipped steps are marked in the progress bar. Nothing is required to finish setup, and anything skipped can still be set later under Settings.

Geändert

  • Expenses on the dashboard state their period: The expense total was always the current month but sat under a general heading, so it looked like a lifetime total. It now names its timeframe and follows the period selector.
  • Trial periods are now real: An unexpired trial grants full access to the app. Previously every trial account was sent to the subscription page immediately, so the 30-day trial granted nothing.
  • Setup interview available in English, French and Italian: The onboarding wizard was German-only; it now follows your language setting like the rest of the app.

Behoben

  • Setup interview failed on the last step: Finishing the setup could fail with a technical message (Unexpected token '<') instead of completing. Requests the wizard makes were being answered with a sign-in page rather than data. Uploading a logo during setup silently did nothing for the same reason; both now work, and a failed logo upload is reported instead of being swallowed.
  • Phantom vendor bills on the dashboard: The Open vendor bills widget counted ordinary expense receipts as vendor bills, showing bills that were never entered. It now reads actual vendor bills.
  • Wrong dunning count: Open invoices could claim invoices were in dunning when they were not — drafts, scheduled invoices and paused cases were all counted. Only genuinely open, non-paused invoices with a reminder sent are counted now.
  • Revenue figures ignored the selected timeframe: Paid, sent, overdue and draft revenue were always lifetime totals shown under a "This month" heading. They now respect the selected period.
  • Assigning the Tester plan: The Tester plan could not be selected when changing a tenant's plan in the platform admin area, even though the plan existed. It is now offered alongside the other plans.

Sicherheit

  • Expired trials are now enforced: A trial that has run out no longer keeps full access to the app. Expired trials are directed to the subscription page until a plan is chosen. Existing trials have been extended so no active account is interrupted by this change.
  • API requests are never answered with a sign-in page: When a request is rejected (signed out, missing two-factor confirmation, no active subscription), API calls now receive a proper error response instead of an HTML page, so failures surface the real reason rather than a parse error.

Hinzugefügt

  • AI bookkeeping landing pages: New localized pages explain Slonge Billing's reviewable AI receipt, booking-assistant, and Smart Inbox workflows with canonical URLs, hreflang links, structured data, sitemap coverage, and privacy-safe conversion events.

Geändert

  • Replayable PostgreSQL migration history: The five original SQLite-shaped migrations have been replaced by a PostgreSQL-native baseline that sorts before every later migration. Fresh development, CI, recovery, and staging databases now use the same prisma migrate deploy path as production.
  • Deterministic container startup: Application containers now run only the checked-in Prisma migrations and fail closed on an error. Historical best-effort DDL, automatic data deduplication, and implicit production seeding have been removed from startup.
  • Immutable production promotion: The production workflow deploys the exact sha- image selected on main, records the previous image, and restores it automatically if startup or health verification fails.
  • Evidence-based AI positioning: Public marketing and Smart Inbox documentation now distinguish deterministic routing, AI-assisted extraction, and human review; unsupported learning, automatic approval, exclusive Swiss processing, immediate email deletion, and unverified review claims have been removed.
  • Clearer AI privacy disclosure: The privacy policy now covers email content, receipt images, and PDF text that may be processed by OpenAI when the corresponding feature is used.
  • Fail-closed database migrations: Deployments no longer auto-baseline an unknown database or continue after a migration error. Historical CRM migrations have been restored, the failed CRM line is reconciled without silent data mapping, and pre-existing invoice-note/MFA objects are accepted only after their database shape is verified.

Behoben

  • Complete opening-balance account selection: Buchhaltung > Anfangssaldo now shows every active, bookable balance-sheet account from the tenant's own chart instead of hard-coded SME number ranges. This includes loans, accruals, and association equity accounts such as 9000–9200, so a valid opening balance can be completed without assigning amounts to the wrong account. Editing an existing opening entry now pre-fills that entry only, rather than including later journal activity.

Sicherheit

  • Guarded baseline reconciliation: Existing databases can move to the PostgreSQL baseline only through a transactional script that checks the exact historical checksums, rejects unresolved migrations or missing baseline tables, and changes only Prisma's migration bookkeeping.
  • Fail-closed CRM recovery: The known production CRM failure now has a read-only, exact-checksum preflight before Prisma marks the zero-step migration rolled back. Legacy CRM enum conversion refuses unsupported mappings or populated obsolete fields, and a final migration asserts the canonical deployed schema.
  • Email MFA without an authenticator app: Password sign-ins now create a short-lived, browser-bound pre-authentication challenge. A normal session is created only after a one-time six-digit code sent to the verified email address. Codes and login grants are stored only as hashes, sending and verification are rate-limited, and existing sessions must sign in again once. Legacy TOTP endpoints and client-controlled MFA state updates are disabled, while existing TOTP data remains unchanged for rollback safety.

Behoben

  • Opening balance missing from the Buchhaltung menu: Anfangssaldo / Opening Balance now has an entry in the sidebar's Buchhaltung dropdown. The page already existed and was reachable by URL, but had no menu link, making it hard to find.

Sicherheit

  • Opening balance entries now recorded in the compliance ledger: Creating or replacing an account's opening balance (Accounting > Opening Balance) now appends journal.created / journal.deleted events to the tenant's audit trail, matching how regular journal entries are already recorded. Previously these entries bypassed the compliance ledger.

Behoben

  • Entry notes missing from the downloaded invoice PDF: The italic note sub-line under a position now also appears on the invoice PDF you download from the invoice page (it was already shown on the detail page and on the emailed PDF attachment).
  • Entry notes in the invoice email: Position notes now also show in the line tables of the invoice email itself, matching the PDF and detail page.

Behoben

  • Doubled material/time lines on invoices (complete fix): The earlier fix only covered the detail page and the email preview. Material costs and time entries folded into an invoice could still appear twice on the downloaded invoice PDF, in the invoice email, and in the e-invoice (UBL) export. All document outputs now list each position exactly once. The invoice total was always correct; only the line list was affected.

Hinzugefügt

  • Entry notes on invoices: The note you record on a material cost (or time entry) now appears on the invoice as a smaller italic sub-line under the position description, on both the invoice PDF and the detail page.

Behoben

  • Doubled material/time lines on invoices: When creating an invoice from a project, the selected material costs (and time entries) could appear twice on the invoice detail page — once as a line item and once as a linked entry. The invoice total was always correct; only the line list was duplicated. Each position is now listed exactly once.

Hinzugefügt

  • Edit and delete material costs: Material costs recorded on a project can now be edited and deleted from the material table, the same way time entries already work. Already-billed or paid material costs can't be deleted, since they belong to an issued invoice.

Hinzugefügt

  • Editable date for material costs: When adding a material cost to a project, you can now set its date instead of always defaulting to today. Handy for recording recurring costs like monthly web hosting fees on the right date.

Behoben

  • Invoice layout restored: invoice and quote previews, prints, and PDFs are no longer rendered as unstyled, column-less text. A recent security hardening step had inadvertently stripped the document template's styling; the styling is now preserved while the same protection against unsafe template markup remains in place.

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.txt now 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 new llms.txt gives 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 .ics files (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 (with hreflang alternates 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-up VM77/VM81/VM26 and 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_migrations was stuck behind old failed rows, so prisma migrate deploy refused to apply newer ones; the docker-entrypoint.sh fallback only covered some). Specifically: ComplianceEvent/DocumentArtifact tables, Settings.attachUblXmlOnSend, AuditLog.tokenId, Client.buyerReference. Hotfix applied directly via ops/hotfix/2026-05-18-apply-missing-prod-schema.sql; docker-entrypoint.sh extended 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 inline React.createElement component, 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 distinct invoice.ubl_validation_overridden event (separate from the existing invoice.ubl_generated), and the auto-attach pipeline records invoice.ubl_validation_failed when it falls back to PDF-only. CLI gains slonge invoice ubl-validate for CI-gated pre-checks and a --force flag for explicit overrides; new MCP tool invoice_ubl_validate lets 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 emits cbc:BuyerReference when set, and SLONGE-CHECK-META-05 surfaces a warning when it's missing.

Geändert

  • buildInvoiceUbl() validates by default: every call site now gets SLONGE-CHECK validation upfront and throws UblValidationError on critical rule failures. Opt out with { validate: false } when a caller wants the bytes regardless. The currency check (CHF-only) moves from the builder's UblBuildError into 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 into src/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-sdk owns the ValidationIssue Zod 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 a DocumentArtifact (kind: invoice_xml_ubl_sent) and an invoice.ubl_generated compliance event, tagged generatedFrom: "lib/invoice-send" to distinguish from dashboard / CLI downloads. The toggle is also available via the CLI/MCP settings_update tool, and the slonge invoice send response envelope surfaces ublSha256 + ublByteSize when 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 into src/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_ubl tool). The XML carries the Swiss QR reference and payment IBAN in cac: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 a DocumentArtifact with a SHA-256 digest and records an invoice.ubl_generated compliance 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 (POST and DELETE /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 the ComplianceEvent ledger. They now fire recordExpenseUpdatedEvent / recordVendorBillUpdatedEvent so an auditor can trace approve → freigegeben → bezahlt and PENDING → APPROVED / SCHEDULED transitions through the hash-chained ledger like every other mutation.
  • quote.sent ledger entries no longer carry internalNotes: recordQuoteSentEvent now strips the internal-only internalNotes field from the outbound-communication event payload, matching the metadata hygiene of the other entity helpers.
  • Distinct quote.accepted compliance event: when a quote status transitions to ACCEPTED (via dashboard PATCH or CLI PATCH), the ledger now records both the generic quote.updated event and a dedicated quote.accepted event. Previously the recordQuoteAcceptedEvent helper 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 ComplianceEvent table now records lifecycle events for every financially-relevant entity, not just invoices. Each entity has dedicated per-action helpers in src/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/mcp transport now produces an AuditLog row alongside the existing ApiTokenUsage request-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 new AuditLog.tokenId column 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 ComplianceEvent ledger (via src/lib/compliance/invoice-events.ts). Sent invoice PDFs are also registered as tamper-evident DocumentArtifact rows 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-server to be published publicly at 0.2.0. Install with npm install -g @slonge/cli once 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 gains slonge dunning list|status|run, slonge report list|export -o , and slonge settings show. Binary exports (Abacus AbaConnect XML, Abacus ASCII .asr) ride the JSON envelope as contentBase64 and the CLI base64-decodes them when -o is given.
  • CLI/MCP Wave 4 — quote + quote-convert. Full CRUD for quotes via the CLI and the MCP server, plus the quote_convert tool that turns an accepted quote into a draft invoice. Convert pipeline extracted to src/lib/quote-convert.ts and shared with the dashboard route (behavior byte-identical for the dashboard caller). CLI quote create accepts line items as a --items-json array; quote-level VAT falls back to settings.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 create accepts --project-id (auto-creates the project's "Default" story) or --story-id. Quick alias slonge time-entry log --project-id --hours defaults 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 monthly aiCallsPerMonth quota; returns 403 FORBIDDEN when the plan doesn't include AI, 429 QUOTA_EXCEEDED when 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 — CLI slonge invoice send and the invoice_send MCP 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 new src/lib/invoice-send.ts module.
  • Project.budget column — CLI/MCP --budget values now persist instead of being silently dropped. Database migration 20260514120000_add_project_budget adds the nullable column; entrypoint script auto-heals existing deployments on container start.
  • API & MCP documentation page (DE + EN) at /docs/api-mcp with 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-sdk workspace package — Zod schemas + HTTP client, single source of truth for CLI, MCP server, and Next.js route validation.
  • @slonge/mcp-server workspace 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-run flags; real test:all / test:full commands wired to workspace scripts.

Geändert

  • Quote PDF generation extracted to src/lib/quote-pdf.ts; dashboard route now delegates and returns application/pdf (previously returned a JSON envelope with rendered HTML).
  • Quote send pipeline extracted to src/lib/quote-send.ts (mirrors src/lib/invoice-send.ts). Dashboard send route now attaches the quote PDF to the outgoing email.
  • src/app/api/ai/receipt/route.ts internals refactored — the OCR pipeline (plan gate, monthly quota check, OpenAI call, account/category resolution, UsageRecord write) lives in the new src/lib/receipt-ocr.ts. The dashboard route's response shape is unchanged.
  • src/app/api/quotes/[id]/convert-to-invoice/route.ts internals refactored — the convert pipeline (find-or-create project, atomic invoice + material costs creation, quote status flip, settings increment) lives in the new src/lib/quote-convert.ts. The dashboard route's response shape is unchanged.
  • Dunning processor refactorsrc/app/api/dunning/process/route.ts (the cron entry point) now delegates each tenant's run to src/lib/dunning-run.ts. Behavior byte-identical for the cron caller; the CLI/MCP /api/cli/dunning/run route calls the same lib with a single tenant id.
  • Report exporters split into shared libssrc/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.json now uses apiToken field (Bearer). Legacy secret field still works on staging with ENABLE_CLI_API=true but prints a deprecation notice; will be removed 2026-11-11.
  • slonge invoice create --description is 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/invoice list 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 Kubernetes CronJob manifests under ops/k8s/jobs/ were never deployed (production runs on a single Docker VM, not on Kubernetes). Set up as a host cron on 85.217.161.119 via 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 — see ops/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: avoid on 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-edges set — 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 /docs is 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 with dunning, smart-inbox, and ai-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 to main. _Note: Currently temporarily disabled due to a missing OPENAI_API_KEY repo secret; will be re-enabled once the secret is set._
  • Doc-update reminder hook: A PostToolUse hook in .claude/settings.json reminds contributors to update docs/de/, docs/en/, and CHANGELOG.md when source files in src/, 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.yaml calls the dunning process daily at 07:00 UTC. Dunning reminders are now sent automatically (auto mode) or shown for approval (semi_auto mode).

Geändert

  • Line-items API: The status=billed filter no longer includes paid entries; use status=paid for 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 address field, but the data model expects addressLine1. 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: pdfkit was 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.md with 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/imprint with 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 /docs with sidebar navigation.
  • Changelog Page: View all updates at /changelog with 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.
v1.0.0

Hinzugefügt

  • Invoicing: Swiss QR-Rechnung with PDF export
  • Time Tracking: Project-based time entries with stories/tasks
  • Expense Management: AI-powered receipt scanning and categorization
  • Client Management: Contact database with project history
  • Project Management: Budget tracking, material costs, and billing workflows
  • Accounting: Double-entry bookkeeping according to Swiss SME standards (KMU Kontenrahmen)
  • Reports: Balance sheet, income statement, and tax exports
  • Multi-tenancy: Isolated workspaces with team invitations
  • Role-based Access: Employee, Accountant, and Administrator roles
  • Billing Plans: Starter, Professional, and Enterprise tiers with Stripe integration
  • Branding: Custom logo and primary color per tenant
  • Notifications: In-app notification system with real-time updates
  • In-app Help: AI chatbot powered by RAG documentation search
  • Mobile UX: Responsive design optimized for 360px+ screens
  • Localization: German and English documentation

Sicherheit

  • Email verification for new accounts
  • Two-factor authentication (TOTP)
  • Session management with sign-out-all capability
  • Rate limiting on sensitive endpoints

Das ist der Anfang. Mehr Updates folgen bald!