Operations··By Forms 365 Workspaces

Equipment booking form for shared team gear

How operations teams run equipment sign-out on SharePoint, including how to stop two people booking the same item for the same week.

Shared gear goes missing. A camera, a projector, a set of field tablets: someone takes them, forgets to say so, and the next person burns twenty minutes hunting. A booking form fixes that, and you already have the place to put it.

What the team actually needs

Most teams do not need a reservation platform. They need to answer three questions fast. Who has the item right now? When is it back? Is anything already spoken for next week?

A single SharePoint list, fronted by a real form, answers all three. The list is the record. The form is how people add to it without seeing the raw columns.

Building it

Start with a list holding the fields you care about: item, person, date out, date due, and a status choice. Then open the form in the designer and shape it so it reads like a request, not a database.

  • Make the item a lookup into your equipment list so nobody free-types "the good camera."
  • Set the due date to default a week out, then let people change it.
  • Hide the status field on the new-item form. Staff should not set their own status to "returned."

The rule engine carries the logic. A requiredIf on the return-notes field keeps it optional until status flips to damaged. That is the sort of small touch that makes a form feel considered rather than generated.

Showing the booking length back to the requester

Before worrying about conflicts, make the request legible to the person making it. A calculatedValue on a read-only "Booked for" field turns two dates into something a human can sanity-check:

{DateDue} minus {DateOut} in days

People catch their own mistakes when the form reflects their input back at them. A fortnight-long booking that was meant to be two days is obvious the moment it says 14.

Stopping two people booking the same thing

This is where most booking forms quietly fail, and it is worth being precise about why.

The no-code rules cannot solve it. visibleIf, requiredIf and calculatedValue all evaluate against the form in front of you, and a clash lives in other rows of the list that the form has never loaded. No amount of rule configuration can see them. Column validation formulas have the same blind spot: they validate one item against itself.

So a genuine clash check needs one short piece of JavaScript. The hook is onBeforeSave, because it is async and returning false cancels the save:

f365.events.onBeforeSave(async () => {
  const picked = f365.field('Item').value; // F365LookupValue or null
  const out = f365.field('DateOut').value;
  const due = f365.field('DateDue').value;
  if (!picked || !out || !due) return true; // let normal validation complain

  const itemId = picked.LookupId;
  if (!itemId) return true; // picker still resolving, nothing to check against

  // Two ranges overlap when each starts before the other ends.
  const clashes = await f365.sp.web.lists
    .getByTitle('Equipment bookings')
    .items.select('Id', 'Title', 'DateOut', 'DateDue')
    .filter(
      `ItemLookupId eq ${itemId}` +
        ` and DateOut lt datetime'${new Date(due).toISOString()}'` +
        ` and DateDue gt datetime'${new Date(out).toISOString()}'` +
        ` and Id ne ${f365.context.itemId ?? 0}`
    )();

  if (clashes.length === 0) return true;

  const first = clashes[0];
  await f365.ui.showAlert(
    `${first.Title} already has this item until ` +
      f365.format.date(first.DateDue) +
      `. Pick different dates or a different item.`
  );
  return false;
});

Three details in there earn their keep. The Id ne clause stops an existing booking clashing with itself when someone edits it, which is the bug every first attempt at this ships with. The LookupId guard handles the moment before the autocomplete has resolved the picked row. And the overlap test is the two-comparison form rather than a pile of date cases, because "each range starts before the other ends" is the whole rule.

If you would rather warn than block, swap showAlert for f365.ui.showConfirm and return its result. Teams that book informally often prefer that: the double booking is usually a conversation, not an error.

Why not a spreadsheet

A spreadsheet has no gatekeeping. Two people edit the same row, one overwrites the other, and now the record is wrong in a way nobody notices until the gear is gone. A form writes one clean row per request and leaves an audit trail behind it.

More to the point, a spreadsheet cannot refuse a booking. The check above is the difference between a record of what people intended and a system that stops the collision happening.

The payoff is quiet. Fewer lost items, fewer "has anyone seen" messages, and a booking history you can actually look back on when it is time to buy more.