Docs

KALENDER

Documentation

KALENDER

The KALENDER plugin shows the appointments from your tenant data centrally
as a Unified Calendar (/kalender) in a shared 4-week grid and provides
the appointments via ICS feeds (ICS Export, /kalender/export) for
external calendar applications (Outlook, Apple Calendar, Google Calendar,
and so on).

The calendar is layer-based: Each layer comes from a
CalendarSourceProvider of the respective plugin and combines its
appointments in one view:

  • Contracts (plugin VERTRAG) — rental periods as multi-day events
  • Time tracking (plugin BUCHUNG) — time entries as single-day events

Further plugins can add their own layers via the same
CalendarSourceProvider interface (details:
How-To/PLUGIN-DEVELOPMENT.md, section "Supplying a calendar (Unified
Calendar)").

> The calendar needs no database table of its own – it reads directly from
> the source plugins. You therefore need at least one active plugin with a
> calendar source (for example VERTRAG or BUCHUNG).


  • Open the calendar view
  • Show/hide layers
  • Configure the ICS settings (visibility, fields)
  • Create and manage ICS feeds (Calendar → ICS Export)
  • Share the ICS link with staff so Outlook/Apple/Google can pull the appointments

1) Calendar view

1. Open Calendar in the menu (/kalender).
2. All active layers appear in the 42-day grid: contracts as multi-day events,
time tracking as single-day events.
3. Use the layer bar to show/hide layers – the setting is stored per user
(pref `kalender.layer.
, e.g. kalender.layer.VERTRAG` /
kalender.layer.BUCHUNG). The default is on.

> Time tracking: Without the buchung.entry.view_all permission, a user
> only sees their own entries in the grid; with view_all, entries from
> all users are shown (foreign entries are prefixed with the user name in the
> subtitle).

2) ICS settings

1. Admin → Calendar → ICS (/settings/admin/kalender/ics).
2. Configure (content settings, affecting the contracts layer only):

  • which fields appear in the appointment title/description (include checkboxes: purpose, tenant name, tenant address, date range, pickup location, return location, inventory list, technicians, link)
  • the LOCATION mode: pickup location / return location / tenant address / no location
  • the base URL (used to build the link to the contract; empty = automatic)

Other layers (e.g. time tracking) are exported as generic events
(title, date, link) – there are no filters by contract status and
no time window. The settings apply globally to all feeds of the
contracts layer (Calendar → ICS Export).
3. Save (POST /settings/admin/kalender/ics).

> Note: These content settings affect all feeds. The preview is now
> available per feed on the ICS export page (see section 3).

3) Create and manage ICS feeds (Calendar → ICS Export)

The export page /kalender/export manages the tenant-wide feeds
(view: permission kalender.kalender.view, edit: permission
kalender.ics.edit):

  • Multiple named feeds per tenant – each feed has its own

token-based URL and its own layer selection (all layers by default).

  • Dynamic generation: The feed content is **generated fresh on every

request** – there is no feed file to keep up to date and no more
AUTOMATE task.

  • Active badge: green "Active" if the feed was accessed within the

last 7 days, otherwise grey "Inactive" (tooltip: last access or
"never").

  • Token rotation per feed (permission kalender.ics.edit): the old

feed URL becomes invalid immediately (404).

  • Legacy migration: Existing K6 feed tokens (Issue #351) are

migrated automatically to the feed "Standard-Feed" – existing
subscriptions keep working.

4) Subscribe in an external calendar

The feed is token-based – every feed URL is an individual, unguessable secret
(Issue #351):

`https://
/ical-feed/<32-hex-token>
/calendar.ics`

1. Copy the feed URL under Calendar → ICS Export ("Copy" button on the feed).
2. Add it in the external calendar as a "calendar subscription" or "Add internet calendar".
3. Outlook / Apple / Google will refresh the appointments periodically – the feed content is generated fresh on every request.

> Each feed is tenant-wide for its selected layers: all appointments of
> those layers, without month or user filtering – the user's layer toggles
> only affect the grid.
>
> With Apple and Google calendars the refresh sometimes takes several hours – that is normal.
>
> Re-import after token rotation: "Rotate token" immediately invalidates
> the old feed URL (404). Affected subscribers must re-import the new feed
> URL – this is the intended protection: only those who know the URL can
> see the appointments.

5) Correcting appointments

Appointments come from the source plugins. If an appointment is wrong in the
calendar, fix it at the source (for example on the contract, plugin
VERTRAG, or on the time entry, plugin BUCHUNG), not on the calendar.


"Nothing shows up in the external calendar"

  • Is the ICS URL correct?
  • Does the feed URL return something (try opening it in the browser)? Wrong token → 404.
  • Force a refresh in the external calendar.

"An old appointment that no longer exists keeps showing up"

  • Are the contracts soft-deleted? The feed content is regenerated on every

request – the appointment disappears after the next refresh in the
external calendar.

  • Force a manual refresh in the external calendar.

"The appointment title is meaningless"

  • ICS settings → adjust the title field format.

"I don't see all time tracking entries in the calendar"

  • Without the buchung.entry.view_all permission, only own entries are

visible – this is by design. Users who may see all entries need the
permission (granted via ROLLEN).

"A layer is missing from the calendar / from the ICS"

  • Missing from the grid? Was the layer hidden via the layer bar? Check the

user's pref `kalender.layer.
` (default is on). The layer toggles
only affect the grid.

  • Missing from the feed? Check the feed's layer selection (Calendar → ICS

Export, edit the feed).

  • Is the source plugin enabled for the tenant? Only active plugins provide

layers.


User area:

  • GET /kalender – Unified calendar view (layers: contracts, time tracking)
  • POST /kalender/toggle-layer – show/hide a layer (pref kalender.layer., active providers only)
  • GET /kalender/export – ICS export page (named feeds, layer selection, preview)
  • POST /kalender/export/create – create a feed (permission kalender.ics.edit)
  • POST /kalender/export/{uuid}/update – modify a feed (name, layers; permission kalender.ics.edit)
  • POST /kalender/export/{uuid}/rotate-token – rotate the feed token (old URL → 404; permission kalender.ics.edit)
  • POST /kalender/export/{uuid}/delete – delete a feed (permission kalender.ics.edit)
  • GET /kalender/export/{uuid}/preview – feed preview (permission kalender.kalender.view)
  • GET /ical-feed/{token}/calendar.ics – ICS feed (public, token-based, generated dynamically on every request, Issue #351)
  • GET /ical/{filename:.+} – disabled (404, former public format)

Admin:

  • GET /settings/admin/kalender/ics – content settings (contracts layer)
  • POST /settings/admin/kalender/ics – save content settings

  • Each ICS feed is tenant-wide for its selected layers: all

appointments of those layers, without month or user filtering. The feed
content is generated fresh on every request (no feed file, no AUTOMATE
task).

  • The layer toggles in the calendar are per user (pref kalender.layer.,

default on) and affect only the grid, not the feeds; the
per-feed layer selection is on the export page (/kalender/export).

  • New layers come from CalendarSourceProvider beans of the respective

plugins – KALENDER itself only filters by tenant and user prefs;
visibility logic (e.g. time tracking) stays in the source plugin.

  • KALENDER works with the active plugin sources (e.g. VERTRAG,

BUCHUNG).

  • Legacy: existing K6 feed tokens (Issue #351) are migrated automatically

to the feed "Standard-Feed" – existing subscriptions and feed URLs stay
valid as long as the feed is not deleted or its token is rotated.

  • Feed management (create, layer selection, token rotation, delete,

preview) is on the ICS export page (/kalender/export). The former
AUTOMATE task KALENDER_ICS (static feed file) is gone: feeds are now
generated dynamically on every request.