← All white papersBuild plan · October 2026

Service Reminders on Microsoft 365

The same standard, for a trade business that lives in Microsoft 365: installed equipment as a list, dates worked out from a schedule list, reminders from Outlook, and each yes written back to the job system once.

8 min read·Free to implement·Published by AI Pathway

Used by

  • Office Manager
  • Microsoft 365 Administrator
  • Service Coordinator

The temptation in SharePoint is a NextDue column, filled in once and sorted by. That is the one thing this plan leaves out. The date is worked out by the daily flow from a Schedule list, so changing the schedule moves every date and nobody edits one. The rest is lists, four flows, and one unique column that stops a second yes making a second job.

In short

  • What this is

    A build plan for the Next Service standard on Microsoft 365. Six lists, four flows, and a booking request written into the job system you already run.

  • The core rule

    Flow 2 reads Assets and Schedule every morning and works each date out. There is no due-date column to go stale when the schedule changes.

  • What it does not do

    No flow picks a time slot or a price, and no message says what a warranty covers. A person books every request in the job system.

  • The hard part

    Claiming the BookingRequests row before calling the job system, so a second yes or a retried flow finds it and writes nothing.

Take the spec to Claude, ChatGPT or Copilot. The sentence to paste is one click away.

Want the whole thing by email?

This paper, plus the rest of the library. One click to stop them.

1. Before you start

Read the Next Service build standard first. It defines its objects, and the lists below are those objects with SharePoint types on them. Shared conventions are in building the standards on Microsoft 365.

Decide how finished jobs get in. If your job system (ServiceM8, Simpro, Fergus, Jobber or AroFlo) has a connector or a webhook, Flow 1 triggers on a job marked complete. If not, a daily export into a list works. Tradify has no public API, so a Tradify business imports by hand and books each yes by hand.

Then write the Schedule list before anything else: one row per equipment type you install or service, with the months between services. Base it on the manufacturer’s instructions or your own advice. An asset whose type has no row is an exception, not a guess.

2. The lists, with their columns

For your developer. Show the fields for your developer
Site: ServiceReminders

LIST  Assets                (one row per piece of equipment, from the finished job)
  AssetId         Text            indexed, UNIQUE, REQUIRED
  CustomerId      Text            indexed, REQUIRED
  SourceJob       Text            indexed. the job it was taken from
  EquipmentType   Text            indexed. matches a Schedule row, or it is an exception
  Make            Text
  Model           Text
  Serial          Text
  InstalledOn     DateTime
  LastServicedOn  DateTime
  WarrantyMonths  Number          as written on the job; blank means no warranty reminder
  Exception       Choice          none | missing_install_date | missing_model
                                  | missing_equipment_type | no_schedule

LIST  Schedule              (the written rule, one row per type)
  EquipmentType   Text            indexed, UNIQUE, REQUIRED
  ServiceMonths   Number          REQUIRED
  ChangedBy       Person
  ChangedOn       DateTime

LIST  Customers
  CustomerId      Text            indexed, UNIQUE, REQUIRED
  CustomerName    Text
  Mobile          Text
  Email           Text
  ConsentSms      Boolean         what they agreed to, from your record
  ConsentEmail    Boolean

LIST  Reminders             (append only)
  Asset           Text            lookup to Assets
  ReminderKey     Text            indexed, UNIQUE. AssetId + Kind + DueOn + Stage
  Kind            Choice          service | warranty
  Stage           Choice          reminder | follow_up
  DueOn           DateTime        as worked out at send time, kept as the record
  Channel         Choice          sms | email
  Body            Note
  SentAt          DateTime
  ReplyText       Note            their words, exactly
  Outcome         Choice          none | yes | stop | unclear
                                  unclear goes to a person

LIST  OptOuts               (no flow clears a row)
  CustomerId      Text            indexed, UNIQUE
  Said            Note            their words, exactly
  ReceivedAt      DateTime

LIST  BookingRequests
  RequestKey      Text            indexed, UNIQUE. AssetId + DueOn: one per date
  Asset           Text            lookup to Assets
  CustomerId      Text            indexed
  ReplyText       Note
  JobNumber       Text            from the job system, once written
  BookedBy        Person          the person who set the time

There is no NextDue column on Assets, on purpose. A stored date is the one that goes stale when the schedule changes.

There is no TimeSlot or Price column on BookingRequests either. A person books the time and prices the work in the job system.

Unique values on Reminders.ReminderKey hold check 5: a second run on the same day cannot add a second reminder for the same date. Unique RequestKey on BookingRequests holds check 11: the second yes fails at SharePoint before the job system is touched.

3. Every rule, and what enforces it

The ruleEnforced byHow
The equipment is taken from the finished job, as recordedFlow 1, Assets.SourceJobFlow 1 copies type, make, model, serial, dates and warranty term from the completed job, and skips a job whose number is already a SourceJob.
A missing install date, model or type goes to a personFlow 1 and Flow 2, Assets.ExceptionEither flow sets Exception and posts the asset to a Teams channel. Flow 2 skips any asset whose Exception is not none.
Due dates are worked out from the schedule, never typed inSchedule list; no NextDue columnFlow 2 adds the Schedule months to LastServicedOn, else InstalledOn, every run. Editing a Schedule row moves every date of that type.
Already booked means no reminderFlow 2, the job system connectorBefore each reminder Flow 2 asks the job system for open jobs on that asset, and skips it if there are any.
Only on a channel the customer agreed to, and a stop is for goodCustomers consent columns, OptOutsFlow 2 checks OptOuts and the consent columns before every send. Flow 3 writes OptOuts on STOP. No flow deletes from it.
A yes becomes one booking request, with no time and no priceFlow 4, BookingRequests.RequestKey, uniqueFlow 4 creates the BookingRequests row first; if it already exists the flow ends. Only then does it create the job and post the job number to Teams.

4. The four flows

For your developer. Show the fields for your developer
FLOW 1  Finished job to asset
  trigger  a job marked complete (connector, webhook or daily import)
  logic    job number already a SourceJob -> stop
           create or update the Assets row from the job, as recorded
           no InstalledOn, Model or EquipmentType -> Exception, post to Teams
  never    fill a gap from the make, or type a due date.

FLOW 2  Daily reminders
  trigger  every morning, 8am
  logic    per asset with Exception none:
             Schedule row for the type? none -> no_schedule, post to Teams
             service due = (LastServicedOn or InstalledOn) + ServiceMonths
             warranty due = InstalledOn + WarrantyMonths, only if set
             per date inside the lead time and not past:
               open job on the asset in the job system -> skip
               OptOuts has the customer -> skip
               no ConsentSms and no ConsentEmail -> no_consent, post to Teams
               create Reminders row (ReminderKey unique) -> send
             a reminder with no reply after the follow-up days:
               one follow_up row (unique key) -> send
  never    send a second reminder or a second follow-up for a date.

FLOW 3  A reply arrives
  trigger  a new SMS reply or an email to the reminders mailbox
  logic    write ReplyText on the Reminders row, exactly as received
           STOP or unsubscribe -> OptOuts row, Outcome stop
           yes, or the booking link -> Outcome yes, run Flow 4
           anything else -> Outcome unclear, post to Teams
  never    reply to the customer on its own.

FLOW 4  One booking request
  trigger  called by Flow 3, or the booking link
  logic    create BookingRequests row, RequestKey = AssetId + DueOn
           it already exists -> stop
           create the job in the job system against customer and asset
           write JobNumber back, post it to Teams to be booked
  never    set a time slot or a price.

Flow 4 claims the SharePoint row before it calls the job system, because the job system does not deduplicate for you. A flow that writes the job first and the row second makes two jobs the day the first call times out and retries.

5. The order to build it in

  1. Create the six lists from the schema, with the unique columns set.
  2. Write the Schedule list, then build Flow 1 and prove an asset with no install date lands as an exception.
  3. Build Flow 2 sending to a test mobile only, and prove changing a Schedule row moves the dates.
  4. Build Flow 3, and prove STOP writes OptOuts and an unclear reply reaches Teams.
  5. Build Flow 4 against the job system, and prove two YES replies leave one job.

6. Four traps specific to this build

A NextDue column, because it is easier to sort

It is right on the day it is filled in and wrong the day the schedule changes. Work the date out in the flow, and sort a view on a calculated value if you must.

Letting Copilot fill a missing model or warranty term

A plausible model or a usual five-year term is a guess written into the record. Leave it blank, raise the exception, and let a person check the unit.

Writing the job before claiming the row

Power Automate retries a step that times out. If the job is created first, the retry creates a second one. Claim the unique row first.

Warranty wording that sounds helpful

"Your repair is covered until..." is a statement about the customer's rights. The message states the expiry date on your record and nothing else.

7. Where the automation stops

  • Booking the time and pricing the work for every booking request.
  • Writing and changing the Schedule list.
  • Fixing any asset with a missing install date, model or type.
  • Answering any reply Flow 3 marks unclear, and taking anyone off OptOuts, which happens only if they ask.

The pass test. Change the hot water row in Schedule from twelve months to six and run Flow 2: every hot water date moves, and nobody edited one. Add a test customer to OptOuts: they get nothing. Put your own mobile on a test customer with a unit inside the lead time, reply YES to the reminder, then YES again: one BookingRequests row and one job in your job system. A few minutes on your own tenant.

Related reading