# Desk booking template: SharePoint lists

The SharePoint version of the VirtoSoftware desk booking template. Two lists on one site:
**Desks** and **Desk Bookings**. The script `desk-booking-sharepoint-list.ps1` creates both;
this page describes the same lists for anyone who prefers to build them by hand.

Guide: https://www.virtosoftware.com/microsoft-365-guides/desk-booking-template/

## List 1: Desks

| Column (display name) | Internal name | Type | Settings |
|---|---|---|---|
| Desk ID | Title | Single line of text | The built-in Title column, renamed. Required. Indexed, enforce unique values. |
| Floor | Floor | Choice | Required. Floor 1, Floor 2 (your floors). Use single line of text if floors change often. |
| Zone | Zone | Single line of text | For example Quiet zone, Team area. |
| Features | Features | Choice, multiple selections | Dual monitor, Standing desk, Near window, Docking station. |
| Status | DeskStatus | Choice | Required. Active, Out of service. Default: Active. Indexed. |

## List 2: Desk Bookings

| Column (display name) | Internal name | Type | Settings |
|---|---|---|---|
| Title | Title | Single line of text | Required. What the calendar shows, for example `F1-03 Anna Becker AM`. |
| Desk | Desk | Lookup to Desks, column Desk ID | Required. Indexed. Delete behaviour: restrict (a desk with bookings can't be deleted; set it to Out of service). |
| BookingDate | BookingDate | Date and time, date only | Required. Indexed. |
| Period | Period | Choice | Required. Full day, AM, PM. Default: Full day. |
| Employee | Employee | Person or group, people only | Required. One person. |
| Notes | BookingNotes | Multiple lines of text, plain | Optional. |
| DeskDateKey | DeskDateKey | Single line of text | Indexed, enforce unique values. Hidden from the default New and Edit forms. Written by a flow or a form, never by hand. |

**List validation** (List settings > Validation settings):

- Formula: `=[BookingDate]>=TODAY()`
- User message: `BookingDate cannot be in the past.`

The rule is checked every time an item is saved, so a booking whose date has passed can no longer
be edited. It can still be deleted.

**Views**

- **Upcoming** (default): BookingDate is greater than or equal to `[Today]`, sorted by BookingDate,
  then Desk.
- **Calendar**: view menu > *Create new view* > *Calendar*. Start date on calendar: BookingDate.
  End date on calendar: BookingDate. Title of items on calendar: Title. A booking appears as a
  single-day entry.
- **All Items**: every column, including DeskDateKey, for the admin.

No JSON column or view formatting is included.

## What DeskDateKey does, and what it doesn't

A SharePoint list can't stop two bookings of the same desk on the same date on its own.
*Enforce unique values* works on one column at a time, and a calculated column (Desk plus date)
can't be made unique. So the key is a plain text column that something else fills in:

```
<Desk ID>|<BookingDate as yyyy-MM-dd>|<Period>      for example   F1-03|2026-11-04|AM
```

Once the key is written, SharePoint refuses a second booking with the same desk, date and period:
two AM bookings, two PM bookings or two Full day bookings. It does **not** catch Full day next to
AM or PM, because those keys differ. That case needs a check in the flow or form. SharePoint
compares only keys that are filled in: a booking without a key isn't checked at all, so every
booking needs one.

Two ways to fill the key:

1. **In the form (preferred).** A Power Apps list form (*Integrate* > *Power Apps* >
   *Customize forms*) builds the key when the employee saves. A duplicate is rejected before the
   booking exists. The same form can look up other bookings for that desk and date and block a
   Full day / half day clash.
2. **In a flow.** Trigger *When an item is created* (SharePoint). *Get items* on Desk Bookings,
   filtered by the same Desk and BookingDate. If another booking exists and either one is Full day,
   or *Update item* fails because the key already exists: *Delete item* and *Send an email (V2)*
   to the employee. Until the flow has run, both bookings are in the list: the new booking has
   no key yet, and an empty key isn't compared, so nothing blocks it.

Build the date part of the key from the date as SharePoint stores it, formatted yyyy-MM-dd, and
check one item to make sure the time zone didn't move it by a day.

## Reminder (optional)

A *Scheduled cloud flow* with the *Recurrence* trigger, once a day: *Get items* where BookingDate
is tomorrow, then *Send an email (V2)* to each Employee with the desk and period.

## Limits

- No check-in and no auto-release: a desk booked by someone who stays at home stays booked.
- Bookings don't appear in anyone's Outlook calendar unless a flow creates the event.
- No floor map, and no parking or equipment in the same booking.
- Anyone with edit rights on the list can change other people's bookings, unless you restrict
  item-level permissions (List settings > Advanced settings > Item-level Permissions: *Create
  items and edit items that were created by the user*).
