Get a quote
Process

Separating appointments and service requests: why one form can't carry both

An appointment attaches to a place; a service request attaches to an installed unit or a plan. Three builds show which record carries that difference, and what breaks when none of them does.

Algoriel 13 min read
Separating appointments and service requests: why one form can't carry both
In this article
  1. When every request lands on one form, the queue is sorted by phone
  2. A site survey cannot behave like a breakdown call
  3. Holding the hour is not the same as holding the plan
  4. A booking, a cancellation and a no-show are three different events
  5. What carried the difference in three builds
  6. The separation belongs in the data model, not the form
  7. Can the separation itself be configurable
  8. Signs that your business needs separate intake flows

A survey appointment books a date against an address; a service request attaches to a machine already installed, or to a plan already running. A shared form with a type field labels the request; the distinction has to live in the record that stores what each one attaches to. At Diotek a survey holds an address and a time window but no product code, because which unit fits is what the visit decides.

When every request lands on one form, the queue is sorted by phone

Diotek installs and services air conditioning and ventilation systems. Two unlike requests reach a company like that. One comes before a sale. The other comes after an installation, and it concerns a machine already on a wall. Both used to arrive over the same phone line, and what a caller actually wanted only became clear once someone asked. Classification was a human task, performed live, with no record of the decision.

The cost of that arrangement shows up at the start of a season. Heating or cooling demand concentrates into the same few weeks, and the two request types stack on top of each other. A visitor who reaches a busy line rarely calls back. The site could not catch that visitor either, because it stood outside the flow as a brochure with a phone number on it.

The failure is not slow staff. It is that intake was bound to a single channel, and a synchronous one at that. A phone call requires both parties to be free at the same moment. Every moment that condition fails, a request that existed in someone’s head never becomes a request in the business. In the current setup, intake no longer depends on the phone line; survey and service requests arriving outside working hours still land as written records. Because they are written, who asked for what, and when, no longer depends on anybody remembering the call.

A written record gives operations a second thing as well: an order. Requests taken by phone carry no reliable sequence, because some of them never arrived at all. A written record carries the moment it was created on itself. A team opens the day by looking at a queue. That is the step that has to be settled before the two types are split at all — the split only starts to mean something once every request lands somewhere.

None of this pays off everywhere. If request volume is low and every incoming request is the same shape, a second flow carries nothing. Adding a second queue to a brochure site that needs one contact form just adds an empty box to maintain. What forces the separation is not the number of requests. It is that the requests are not alike.

A site survey cannot behave like a breakdown call

In this trade, unit capacity depends on the space. Room volume, insulation and which way the wall faces decide what equipment will do the job, so nobody can quote before seeing the place. That is why a survey appointment centers on the location. A visitor asks for a date for an address before choosing any equipment. The request carries no product code at all — it carries an address and a window of time.

A service request is built from the opposite end. A machine is already installed, and the request attaches to that machine. Maintenance and fault reports open from the site and reach operations in their own flow, without entering the survey queue. Because the queues are separate, one of them swelling at season peak does not slow the other down.

On Diotek’s HVAC site we built these as two flows from the first day rather than one flow with a type field bolted on afterwards. The two records ask for different things from the start: the survey record for an address and a window, the service record for the unit it concerns.

We did consider the cheaper-looking route: one form, plus a request type field. It falls apart at validation. A survey needs an address and does not need a unit; a service request needs the unit and can manage without a detailed address. On one shared form you cannot make both mandatory, and if you make both optional the record is created incomplete. An incomplete record sends the work straight back to the phone, which is the problem you started with. Pushing the distinction down to a field does not remove it. It relocates it to a layer that cannot resolve it.

Holding the hour is not the same as holding the plan

Dental treatment rarely finishes in one visit. A plan is drawn tooth by tooth: which procedure goes on which tooth, ordered into sessions that spread across weeks and get revised along the way. The plan is therefore its own record, standing independently of any calendar entry.

In the dental clinic CRM, where each appointment attaches to a specific step of that plan, the calendar is not a second copy of the treatment. It is the projection of the plan onto time. When a step changes, or a session is inserted, the calendar moves with it. No appointment is left pointing at nothing, because there is always a step on the other end of the link.

Before that, the clinic ran on a general-purpose booking tool. The tool held the hour and never the step. Where a patient stood in treatment had to be reconstructed from the calendar: scroll back through past appointments, remember which ones were cancelled, count the remaining sessions in your head. Because that reconstruction happened fresh each time, two people looking at the same patient could arrive at two different answers, and neither could prove the other wrong.

What carries the difference here is not a screen. It is a link. The appointment record stores which plan step it belongs to. Since the link lives in the record, a change to the plan reaches the calendar without anyone dragging appointments around.

A second benefit shows up in reporting. Because the plan stands as its own record, how many steps are done, how many are waiting and which session slipped can all be read off the plan rather than counted by scrolling the calendar. A clinic manager sees where a patient stands in treatment on one screen.

For work that finishes in a single session — one consultation, one examination, one measurement — binding an appointment to a plan step adds a layer with nothing in it. If the plan has exactly one step, the appointment already is the plan. What justifies the link is that its steps depend on each other’s order.

A booking, a cancellation and a no-show are three different events

In a Pilates studio, customers do not pay per class. They buy packages. That one fact changes what a booking record means: it stops being a block that occupies space on a calendar and becomes a movement that posts against a balance.

In the Pilatesco system, where a booking, a cancellation and a no-show are kept as three distinct records, writing a booking to the calendar deducts one class credit from the package. The balance sits on the customer record rather than in a separate ledger. Cancellation, no-show and a completed class each post to that balance differently, and which case returns the credit is written as a rule instead of being negotiated case by case.

On the calendar, a cancellation and a no-show look identical: the hour ended up empty. Against the balance they are not remotely the same. One may return the credit and the other may not, and which is which is the studio’s own commercial decision. If that decision is not encoded, every instance gets settled over messages, and two customers asking the same question in the same week can get two different answers.

Capacity carries a parallel distinction. How many people an hour can hold is set by instructor, equipment and the slot together, not by a single seat count. Private sessions and group classes share one calendar while each opens under its own capacity rule.

Finally, two different clocks meet on one record. An invoice arises the moment a package is sold, while usage plays out across weeks of calendar. A sale belongs to an instant, usage to an interval. Held apart, matching what was sold against what was used becomes a month-end reconciliation done by hand.

What carried the difference in three builds

All three builds answer one question against a different object: what does this request attach to? The answer might be a location, an installed unit, a step in a plan, or a package balance. That attachment is what carries the separation each time. The table below sets what held the difference beside what would have happened without it.

Which two types were splitWhich record carries the splitWhat would have happened otherwise
Pre-sale site survey × post-installation service requestThe survey record centers on location and date, the service record on the installed unit; each request reaches operations in its own flowAt season peak both types pile onto one phone line, sorting happens in conversation, and a visitor who hits a busy line is lost
Appointment × treatment planThe appointment is a record bound to a step of a tooth-by-tooth plan split into sessions; when the plan moves, the calendar movesThe software keeps only the hour; a patient’s position in treatment is reconstructed from the calendar and appointments end up orphaned
Booking × cancellation and no-showThe package balance held on the customer record, with an explicit rule for how each event posts to itRemaining credits are tracked in a notebook, and whether a cancellation returns a credit is answered over messages

In a system that works, a separation disappears from view; the third column describes the version without it.

The separation belongs in the data model, not the form

Two intake flows do not mean two systems. At Diotek, the survey and service flows run inside one Laravel application alongside the public marketing pages, and the request records share a MySQL schema with the content. Because the schema carries the distinction, a single application produces two already-separated queues.

In practice this meant no second server, no second panel and no second admin interface. What it did require was defining two request types as two records with different fields and different validation rules. Inertia handles page transitions on the client while routing and form validation stay in Laravel. Since the validation rules for both flows live in one place, the type distinction never leaks into client code — the browser does not need to know which field is mandatory for which type.

The seasonal load runs on that same codebase. A Redis cache absorbs the traffic spike at the start of a season, so public pages stop hitting the database on every view, while request submissions still pass through live validation each time. Reads and writes behaving differently is not a reason to split the flows into separate systems.

There is a measurement side to this too. When both types share one record shape, the question of how many surveys came in against how many service requests were opened can only be answered by reading free-text fields. When the record types are distinct, the same question comes straight out of the schema, and nobody has to bolt a classification layer on afterwards to produce a report.

The same principle shows up in billing. In the dental clinic CRM, invoicing does not sit in its own ledger: because the procedure is recorded against the patient, what was treated and what was charged are read from one place. Separation and integrity coexist in one schema — plan, appointment and invoice are distinct records arranged around the same patient.

Building request records that attach to a customer, an installed unit or a plan is the first thing we settle in our CRM work, before any interface exists. Reversed, the order produces a good-looking screen and an incomplete record underneath it.

Can the separation itself be configurable

In all three builds above, we defined the distinction. The next question is whether a business can define it for itself. That is what we are working through in AlgoRandevu, which we are currently building.

Rather than baking slot length and the spacing between bookings into a sector’s assumptions, we are keeping them as product settings, so that changing a rule does not mean changing code. Slot length differs between a clinic, a studio and a workshop, and so does the gap between slots. Compiling that into the product means a new release for every business that books differently.

In the structure we are building, an appointment can attach to a person, a room or a piece of equipment; the business picks its own resource rather than us writing a separate build per sector. We are putting the product on the same Laravel and Inertia base as AlgoKlima and AlgoCar, keeping booking records in MySQL and wiring Redis as the cache layer. Configurability, in other words, does not call for a new stack; it calls for a definition layer. The product is still in development.

When the objects at the center of two types differ fundamentally, as at Diotek with a location on one side and an installed unit on the other, building two explicit flows can still be the right call rather than reducing the difference to a setting. Configurability absorbs variation among rules that resemble each other. It does not squeeze unlike objects under one template. So a configurable appointment definition does not replace the decision to build separate flows; it narrows the set of cases where that decision is needed.

Signs that your business needs separate intake flows

Each of the three builds here started with the same symptoms. If you recognise one of them in your own operation, the record that should carry the distinction has not been built yet.

If what an incoming request actually is can only be established by talking on the phone, classification belongs to a person rather than to a record. That was exactly the situation at Diotek, and it persisted for as long as requests failed to land in writing.

If your software holds the hour but not the step the work is on, appointments are not attached to a plan. In the dental clinic the visible consequence was that the same patient’s status looked different to two members of staff.

If whether a cancellation returns a credit gets answered over messages, cancellation and no-show are being treated as one event. At Pilatesco, moving that rule into the system took the question out of weekly negotiation.

If a business is bending its own process to fit its software, the definition of an appointment has been fixed to one trade.

All four point the same way: information a system does not hold is held by a person, and information held by a person goes missing during holidays, busy weeks and staff turnover. In our management software work, carrying appointments, plans and invoices as separate records inside one application, the first thing written is never a screen — it is these attachments. Screens get redrawn later. What a request attaches to does not.

Key takeaways

  • A survey appointment attaches to a location and a service request to an installed unit; the record, not the form, carries the difference.
  • If request intake depends on a phone line, requests arriving outside working hours are lost instead of landing as written records.
  • Software that stores the time slot without linking it to a plan step knows when the work happens, but not where in the work you are.
  • Booking, cancellation, and no-show must each post to a package balance under an explicit rule that says which one returns the credit.
  • Separate request flows do not require separate systems; at Diotek both flows share one Laravel application and one MySQL schema.

Questions this article answers

  • Why shouldn't a site survey and a breakdown call go through the same form?

    Because they attach to different things: a survey appointment attaches to a location, a breakdown call to an installed unit. At Diotek both used to arrive over one phone line, and what a request actually was only became clear in conversation; at the start of the season the two types piled on top of each other. In the current setup, survey and service were built as separate flows from the start.

  • How does an appointment know which step of the treatment plan the patient is on?

    The appointment itself doesn't; the record it attaches to does. In the dental clinic CRM, the treatment plan is built tooth by tooth and splits the work into ordered sessions. Each appointment attaches to a specific step of that plan. The general-purpose software the clinic used before kept the time slot but not the position in the plan; once the link existed, the calendar could be read from the plan.

  • What happens to booked appointments when the plan changes?

    The calendar shifts with the plan. In the dental clinic CRM an appointment is not a free-standing time block; it is the calendar side of a step in the treatment plan. When a step changes or a session is added, later appointments settle into the new order. If only the time were stored, every change would mean moving appointments by hand; because the link lives in the record, changes flow from plan to calendar.

  • Does a cancelled class return the credit, and does a no-show work the same way?

    They don't work the same way; which case returns the credit is defined as a rule. In the Pilatesco system, customers buy packages rather than paying per class; writing a booking to the calendar deducts a class credit, and the balance sits on the customer record. Cancellation, no-show, and a completed class each post to that balance differently. The invoice is created when the package is sold; usage is read from the calendar.

  • Can two request types live in one application, or do they need two systems?

    One application is enough; the separation lives in the data model, not in separate systems. At Diotek, the survey and service flows run in the same Laravel application, on the same MySQL schema, alongside the public pages. Inertia handles page transitions on the client while routing and validation stay in Laravel, and a Redis cache absorbs the seasonal traffic on the same codebase. The two flows are two record types in one schema.

About the author

Algoriel

Remote web software agency

We build custom web and mobile software for businesses. Here we answer the questions that come up while your software is being built and after it goes live.

Tags:
  • appointment scheduling
  • service requests
  • data modeling
  • crm
  • process design

Have a system to build?

If there is a system you want built, the quote form is the place to describe it.