Build guide — Power Platform

ABE / T3B Room Booking

A hourly room-booking system for T3B, built entirely on SharePoint, Power Apps, Power Automate and Outlook — no third-party tools, no IT procurement beyond your existing Microsoft 365 licence.

13 rooms · 2F & 3F Hourly slots · Mon–Fri Book up to 1 month ahead QR code → per-room screen SharePoint permitted list
01

Solution architecture

Four Microsoft 365 components, each doing one job. SharePoint is the single source of truth; Power Apps is the front door for staff; Power Automate handles everything that needs to happen in the background; Outlook delivers the human-readable confirmations.

SharePoint Rooms · Bookings · PermittedUsers lists Power Apps Overview screen + per-room QR screen Power Automate Confirm · remind · cancel · sync Outlook Email confirmation + calendar invite QR code on door (13 printed, 1/room) Staff (permitted list) Entra ID login triggers on list change
Teal = live read/write path (Power Apps ↔ SharePoint). Amber = automated background path (Power Automate ↔ SharePoint ↔ Outlook).
No IT procurement required — all four components are already included in your existing Microsoft 365 / SharePoint Online licensing. The only admin task is confirming your Power Apps environment has a Power Automate premium connector allowance if you use the Office 365 Outlook "Create event" action (standard connector, included in most E-tier licences — check with IT once).
02

Data model — 3 SharePoint lists

Build these first. Everything else (app, flows, QR links) references these lists by ID, so get the schema right before touching Power Apps.

List 1 — Rooms

ColumnTypeNotes
TitleSingle line textDisplay name, e.g. 3F - Meeting Room 1
RoomIDSingle line textUnique short code used in the QR deep link, e.g. T3B-3F-MTG-01
FloorChoice2F / 3F
RoomTypeChoiceMeeting Room / Quiet Room
CapacityNumberOptional, shown on the card
QRDeepLinkHyperlinkAuto-generated once the app is published — see Section 7
ActiveYes/NoUntick to pull a room out of service without deleting it

Seed this list with your 13 rooms:

FloorRoomRoomID
2FMeeting RoomT3B-2F-MTG-01
2FQuiet Room 1T3B-2F-QR-01
2FQuiet Room 2T3B-2F-QR-02
3FMeeting Room 1T3B-3F-MTG-01
3FMeeting Room 2T3B-3F-MTG-02
3FMeeting Room 3T3B-3F-MTG-03
3FMeeting Room 4T3B-3F-MTG-04
3FQuiet Room 1–6T3B-3F-QR-01T3B-3F-QR-06
Your original list had "2Floor - Quiet room" twice with no numbering. I've treated that as two separate rooms (Quiet Room 1 & 2) so QR codes and bookings don't collide — flag if that's wrong and it's a one-line fix in the list.

List 2 — Bookings

ColumnTypeNotes
TitleSingle line textAuto-built: RoomID_Date_StartTime
RoomLookup → RoomsLookup on Title
BookingDateDate onlyNo time portion — time lives in StartTime/EndTime
StartTimeChoice08:00, 09:00 … 17:00 (edit to match your actual operating hours)
EndTimeChoiceCalculated as StartTime + 1hr in the app
BookedByEmailSingle line textCaptured automatically from User().Email — never typed by the staff member
BookedByNameSingle line textFrom User().FullName
PurposeSingle line textOptional free text
StatusChoiceConfirmed / Cancelled

List 3 — PermittedUsers

ColumnTypeNotes
TitleSingle line textStaff name
EmailSingle line textMust match Entra ID login email exactly
DepartmentSingle line textOptional, useful for reporting
ActiveYes/NoUntick to revoke booking access instantly — no app republish needed
Requires SharePoint site owner rights. Whoever creates these three lists needs at least "Edit" on the site — plan for a team member with existing SharePoint admin access to do this, or request it from IT once.
03

Access control flow

The app checks the PermittedUsers list on every launch — not SharePoint item-level permissions — so you can manage who can book from one list without touching site permissions.

Staff opens app (SSO, no login screen) Look up User().Email in PermittedUsers list Found & Active = Yes → Overview / Room screen Not found / Inactive → "Access not enabled" screen
Staff never see a login form — they're already signed into Microsoft 365, and the app silently checks their email against the list.

Power Fx — App.OnStart

// Runs once when the app opens. Sets a global flag used to gate every screen.
Set(varCurrentUserEmail, Lower(User().Email));

Set(
    varIsPermitted,
    CountRows(
        Filter(
            PermittedUsers,
            Lower(Email) = varCurrentUserEmail && Active = true
        )
    ) > 0
);

// Deep-link handling — see Section 7 for how RoomID arrives via QR code
If(
    !IsBlank(Param("RoomID")),
    Set(varDeepLinkRoomID, Param("RoomID"));
    Navigate(scrRoomDetail, ScreenTransition.Fade),
    Navigate(scrOverview, ScreenTransition.Fade)
);
04

Power Apps — the two screens

One app, two entry points. Staff coming from the app icon land on the Overview screen. Staff scanning a QR code on a door land straight on that room's Detail screen. Both share the same booking logic underneath.

ABE T3B Rooms
All floors 2F 3F Meeting Quiet
Fri 31 Jul — pick a date above to change
3F – Meeting Room 2
Capacity 8 · 3F
0809 1011 1213 14
3F – Quiet Room 4
Capacity 1 · 3F
0809 1011 1213
Tap a free slot to book
3F Meeting Room 1
TODAY
31
SAT
01
MON
03
TUE
04
WED
05
Today's availability
08:0009:00 10:0011:00 12:0013:00 14:0015:00 16:0017:00
Book 11:00 today
Need a different date? →
Next 7 days Pick date (up to 1 month)
Available
Booked
Current hour / today

Screen 1 — scrOverview

Screen 2 — scrRoomDetail (QR entry point)

Power Fx — generating the 7-day strip

// Items property of the horizontal day gallery on scrRoomDetail
ForAll(
    Sequence(7, 0),
    {
        TheDate: Today() + Value,
        DayLabel: Text(Today() + Value, "ddd"),
        DayNum: Text(Today() + Value, "dd"),
        IsToday: (Today() + Value) = Today()
    }
)

Power Fx — building the hourly slot grid for a room + date

// Items property of the slot gallery — one row per operating hour
ForAll(
    ["08:00","09:00","10:00","11:00","12:00","13:00","14:00","15:00","16:00","17:00"],
    With(
        {
            _existing: LookUp(
                Bookings,
                Room.RoomID = varSelectedRoomID
                && BookingDate = varSelectedDate
                && StartTime = Value
                && Status = "Confirmed"
            )
        },
        {
            SlotTime: Value,
            IsBooked: !IsBlank(_existing),
            BookedByName: If(!IsBlank(_existing), _existing.BookedByName, "")
        }
    )
)

Power Fx — submitting a booking (with conflict check)

// OnSelect of the "Confirm booking" button
If(
    !IsBlank(
        LookUp(
            Bookings,
            Room.RoomID = varSelectedRoomID
            && BookingDate = varSelectedDate
            && StartTime = varSelectedSlot
            && Status = "Confirmed"
        )
    ),
    // Someone booked it in the seconds since the screen loaded — refuse and refresh
    Notify("That slot was just taken — pick another.", NotificationType.Warning);
    Refresh(Bookings),

    Patch(
        Bookings,
        Defaults(Bookings),
        {
            Title: varSelectedRoomID & "_" & Text(varSelectedDate,"yyyy-mm-dd") & "_" & varSelectedSlot,
            Room: LookUp(Rooms, RoomID = varSelectedRoomID),
            BookingDate: varSelectedDate,
            StartTime: varSelectedSlot,
            BookedByEmail: varCurrentUserEmail,
            BookedByName: User().FullName,
            Purpose: txtPurpose.Text,
            Status: "Confirmed"
        }
    );
    Notify("Room booked — check your email for confirmation.", NotificationType.Success);
    Navigate(scrConfirmation, ScreenTransition.Fade)
)
Why check-then-patch instead of relying on SharePoint alone: SharePoint won't stop two people writing the same slot at the same second. The LookUp immediately before Patch closes almost all of that window; the Power Automate flow in Section 6.2 is the backstop that catches the rare remaining case.
05

End-to-end booking flow

The same flow whether staff start from the app icon or a QR code — they only differ in how they arrive at step 2.

Open app icon → Overview Scan door QR → Room screen Permission check (App.OnStart, Section 3) Pick date (≤ today + 30) and an hourly slot Re-check: still free? LookUp on Bookings Yes → Patch new item into Bookings list No → notify & refresh grid back to slot picker Power Automate flow fires on item created (Section 6.1) Outlook confirmation + calendar invite to booker
The re-check step (amber box) is what makes double-booking practically impossible without needing a premium database.
06

Power Automate — 4 flows

Build these in the same environment as your SharePoint site. Assign each to a different team member (see Section 8) — they don't depend on each other, only on the Bookings list already existing.

6.1 — Booking confirmation

Trigger: When an item is created on Bookings.

  1. Condition: Status is equal to Confirmed
  2. Yes → Office 365 Outlook: Send an email (V2) to BookedByEmail, subject Booking confirmed — {Room} {BookingDate} {StartTime}
  3. Office 365 Outlook: Create event (V4) on the booker's calendar (start = BookingDate + StartTime, end = +1 hour, location = Room) so it shows up in Outlook/Teams automatically

6.2 — Double-booking backstop

Trigger: When an item is created on Bookings.

  1. Get items from Bookings: filter Room eq '@{RoomID}' and BookingDate eq '@{BookingDate}' and StartTime eq '@{StartTime}' and Status eq 'Confirmed'
  2. Condition: count of items > 1 (i.e. a duplicate slipped through the app's own check)
  3. Yes → keep the earliest Created item, set every later duplicate's Status to Cancelled, and email the affected booker that their slot was already taken

6.3 — Daily reminder (scheduled)

Trigger: Recurrence, every weekday at 07:30.

  1. Get items from Bookings: filter BookingDate eq '@{utcNow('yyyy-MM-dd')}' and Status eq 'Confirmed'
  2. Apply to each → Outlook: send a short reminder email with room, time and a "Cancel this booking" link

6.4 — Cancellation notice

Trigger: When an item is modified on Bookings.

  1. Condition: Status changed to Cancelled
  2. Yes → Outlook: send cancellation confirmation to BookedByEmail; delete the matching calendar event created in 6.1
Item created on Bookings list Status = Confirmed? condition branch Send Outlook email Flow 6.1 Create calendar event No → run duplicate check Flow 6.2
Flow 6.1 in detail — the pattern is identical for 6.3 and 6.4, swapping the trigger and the email content.
07

QR code deep links

Each printed QR code encodes a URL that opens the Power App and passes the room's code as a parameter, which App.OnStart (Section 3) reads and routes straight to that room's Detail screen.

Link format

https://apps.powerapps.com/play/e/{environment-id}/a/{app-id}?RoomID=T3B-3F-MTG-01
  1. Publish the app once, then open it via Power Apps Details to copy the environment-id and app-id from the play link.
  2. Build 13 links, one per RoomID from Section 2's Rooms list — a quick Excel formula does this in one column.
  3. Paste each link into qr.io or any offline QR generator (or generate via a Power Automate "Create QR code" step if you'd rather keep it all in Microsoft 365).
  4. Print and laminate one per door, sized ~6×6cm, at eye level beside the room nameplate.
Test before printing all 13. Print one QR code first (e.g. 3F Meeting Room 1), scan it with a personal phone camera, confirm it opens straight to that room's 7-day view with today focused — then batch-print the rest.
08

Build plan — delegating across your team

Six work packages that can run largely in parallel once the data model (Section 2) is signed off. Suggested split across your 7 direct reports — adjust based on who already has Power Platform exposure.

PACKAGE 1

SharePoint lists

Create the 3 lists exactly per Section 2, seed the 13 rooms and the permitted staff list.

Owner: 1 person · SharePoint edit rights needed
PACKAGE 2

Power Apps — Overview screen

Build scrOverview: room gallery, floor/type filters, date picker, slot strip.

Owner: 1–2 people · needs Package 1 done
PACKAGE 3

Power Apps — Room Detail screen

Build scrRoomDetail: 7-day strip, today focus, hourly grid, booking dialog, deep-link handling.

Owner: 1–2 people · needs Package 1 done
PACKAGE 4

Power Automate flows

Build all 4 flows from Section 6, test each against a dummy booking.

Owner: 1 person · needs Package 1 done
PACKAGE 5

QR generation & printing

Generate, test, print and post 13 QR codes once the app is published.

Owner: 1 person · needs Package 3 published
PACKAGE 6

UAT & rollout comms

Run the testing checklist (Section 9), write the one-page staff how-to, announce go-live.

Owner: whole team · needs all above done
09

Testing & rollout checklist

10

Training & onboarding

Two audiences, two different needs.

For your 7 direct reports (builders)

For general staff (bookers)