Entities and activities
The second half of the model. Building blocks describe what changes hands when a customer pays. Entities describe what the sale is about, and activities are what you remember about it over time. This is how a business gains a memory.
The mental model answers "what changes hands when a customer pays?" This page answers the two questions that come after it:
- What is the sale about? A repair is about a car. A grooming is about a pet. A refill is about a patient. A bag of coffee is about nothing in particular.
- What do you remember about it? The odometer reading, the vaccine given, the note that the customer approved the work, the reminder that service is due.
Get these two right and a plain point of sale becomes software that remembers: the mechanic sees the car's history before touching it, the vet sees the weight trend, the pharmacist sees the last refill. That memory is the whole game. It drives repeat business, it powers reminders, and it is what makes the same platform feel purpose built for a garage, a clinic, or a rental yard without a line of vertical code.
Two words, precisely
Entity. A thing an order can be about that has a life of its own: a vehicle, a pet, a device, a rental kayak, a rented unit, a prescription. It persists between orders and accumulates a history. Entities are minted in a lightweight registry; each one has a type (vehicle, pet, ...), a label ("Toyota Corolla"), some fields (plate, year), and a single parent that says who or what it belongs to.
Activity. Anything you record. A note, a measurement, a checklist result, a reminder, a status change, a link. Every activity attaches to exactly one thing: an order, a customer, or an entity. Activities are typed (a reading knows it is a number with a unit; a reminder knows it has a due date), which is what lets the platform chart them, flag them, and act on them.
The rest of this page is about two decisions: what to model as an entity (and how heavily), and where each activity should attach.
The one rule for where activities go
An activity attaches to whatever it is actually a fact about. Not where it was captured, not who was standing there, what it is true of.
| What you are recording | It is a fact about... | Attach to |
|---|---|---|
| Staff note ("customer approved the rotor skim"), status change, payment, discount, refund reason | this transaction | the order |
| Brake pad thickness, odometer, pet weight, blood pressure, inspection result, dispensed quantity | the thing being serviced | the entity (or the customer, see the ladder) |
| Allergies, colour formula, preferred contact, lifetime value, which unit they rent | the person | the customer |
The trap, and it is the single most common modelling mistake, is putting a fact about the subject onto the order. A "brake pad 2.0mm" reading recorded on order #1042 dies with #1042. Next visit is a different order, the car shows no history, and the entire reason the car is an entity is gone. A reading is never about the order. It is about the car, captured during the order. It lives on the car, stamped with the order it came from, so it shows on this order and is still there at the next service.
If you find yourself attaching a measurement of the subject to an order, stop. That fact belongs on the subject (the entity, or the customer). Orders hold what is true of the transaction only: notes, status, money.
The ladder: choosing how much to model
Not everything a sale is "about" needs to be a full entity. The model is a ladder, and you pick the lowest rung that carries what you need. Reaching for a heavy entity when a light one will do is the second most common mistake.
| Rung | Shape | The subject... | Lives on | Typical verticals |
|---|---|---|---|---|
| 0 | No subject | ...does not exist | nothing | retail, food, restaurant |
| 1 | Context on the customer | ...is the customer, or is a simple fact about them | the customer (fields + activities) | salon, gym, property (which unit + complaints), personal training |
| 2 | A customer's owned entity | ...is a distinct thing the customer owns, with its own history | an entity, parent = the customer | auto (vehicle), vet (pet), device repair, dental (patient) |
| 3 | A business or landlord owned entity | ...is a thing the business or a third party owns, used across many customers | an entity, parent = the business, a location, or another entity | rentals (the kayak), shared assets, landlord centric property (the unit) |
The test for which rung
Ask, in order:
- Is the order about a specific thing at all? No, retail. Rung 0. Done.
- Does that thing need a life across visits or across customers?
- No, it is just context on this person (their hair formula, which unit they rent). Rung 1. Record it as fields and activities on the customer. Do not mint an entity.
- Yes, it accumulates a history that must outlive a single order. Go on.
- Who owns it?
- The paying customer owns it (their car, their pet, their phone). Rung 2. Mint an entity, parent it on the customer.
- The business owns it, or a third party does, and it is shared across customers (a rental van, a landlord's unit). Rung 3. Mint an entity, parent it on the business, a location, or the owner.
subject_entity_type on a service is really choosing the rung. null = rung 0, "customer" = rung 1, a synthetic type like "vehicle" = rung 2 or 3 depending on who you parent it under. One field, the whole ladder.
What an activity can be
Activities are typed. The type is what lets the platform treat a measurement as a number to chart, a reminder as something to fire, a checklist as pass or fail. The common kinds:
| Kind | What it is | Example | Usually attaches to |
|---|---|---|---|
| Note | Free text for the team | "Customer nervous around clippers" | order (transaction note) or customer (durable trait) |
| Field | A pinned, single value that is the current truth | Allergies: penicillin; Plate: GR-4821-24 | customer or entity |
| Reading | A number (or money, or date) with a unit, kept as a series | Odometer 84,120 km; Weight 38 kg; BP 138/88 | the entity (or customer at rung 1) |
| Check | A structured pass/fail or multi point result | 12 point inspection: 2 advisories | the entity, stamped with the order |
| Reminder | A future dated prompt, often SMS | Service due at 94,120 km | the entity (so it survives the order) |
| Reference | A link from one record to another | This order is about vehicle X | the order (points at the entity) |
| Automation event | Something a pack did on its own | "Refill reminder sent" | wherever the pack acted |
A field and a reading look similar but differ in intent: a field is the current value (you overwrite it), a reading is a point in a series (you keep them all). Odometer is a reading (you want the trend). Allergies is a field (you want the latest truth). When in doubt: if you would ever plot it or want the previous value, it is a reading.
Declaring a reading's shape
A reading is only as useful as what the pack declares about it. On the reading's schema, each field can carry a few annotations that tell the platform how to show it and, later, how to aggregate it. They are optional and additive; nothing breaks without them, but a reading that declares them charts cleanly and rolls up correctly.
| Annotation | On | Says |
|---|---|---|
x-unit | a field | Its unit label, e.g. mmHg, km |
x-order | a field | Where it sits in the display order |
x-icon | the reading | Which icon represents it |
x-metric | a field | This is the number to chart and roll up (one per reading) |
x-aggregate | a field | How it rolls up over time: avg, sum, or last |
Blood pressure declares systolic as the metric, averaged, in mmHg; the platform then trends it, and when a report later asks "average BP over 90 days" it can answer without anyone re-instrumenting the pack. Declare the metric once on the definition and it applies to every reading already recorded, which is what keeps the reporting layer something that can be generated later rather than built up front.
How an order learns what it is about
Nobody decides "attach the pet to this order and the car to that one" by hand. The service declares its subject, and everything follows.
The declaration
Every product or service carries an optional subject_entity_type. Packs ship it; merchants can set it on their own services.
Auto Care Pack Vet Pack
entity type: vehicle entity type: pet
Brake service → vehicle Grooming → pet
Oil change → vehicle Vaccination → pet
Barber (rung 1) Retail
Haircut → customer Coca-Cola 1.5L → (nothing)The value must be a registered entity type (or customer, or blank). That constraint is the bridge: a service can only be "about" something the platform knows how to model.
Capture, at whichever point comes first
Usually at checkout: you have already picked the customer, you add "Brake service", the cart reads its subject_entity_type, sees it needs a vehicle, and resolves it:
- Customer has one vehicle, attach it silently.
- Customer has several, ask "which vehicle?"
- Customer has none, offer "add vehicle" inline (plate, year), then attach.
- No line item declares a subject, ask nothing, attach nothing. (The retail order.)
But checkout is not the only capture point. A drop off, a booking, or a quote can set the link earlier, before there is even a payment. The rule is simply: the link is written whenever the subject first becomes known.
The link itself
The order carries a lightweight reference to the entity. The entity is not re-parented onto the order (that would silo it, the same trap as a reading). The car stays owned by its owner; each order that touches it holds a pointer. Readings taken during the order carry the reverse stamp (which order they came from), so the order can show "what was recorded here" and the car keeps the reading forever.
The separation that makes the whole thing hold: subject is not who transacts
This is the load bearing idea, and the vertical that proves it is the pharmacy.
When your mother takes you to the hospital, they record against you, not your mother. The customer on the order is the patient. Your mother is not the customer, she is not in the record as anything, she simply hands over the money. The prescription, the dispensing log, the interaction check all attach to the patient, because the patient is who the order is for.
So there are two independent axes, and confusing them invents problems that do not exist:
- Who the order is against (the customer / patient / owner). This owns the subject and is what records attach to.
- Who tenders the payment (cash from a relative, a card, an insurer). This is a payment concern, tracked as payment, not as the customer.
Once these are separate, a whole class of apparent edge cases dissolves:
- Caregiver pickup (someone collects a prescription for a relative): order is against the patient, the relative is just tender. No problem.
- Insurance job (the insurer pays to fix the policyholder's car): order is against the policyholder, who owns the car; the insurer is a payer, handled in payments and settlement, not in the entity.
- A friend drops off and pays for your car: the order is against the car's owner. You identify the owner as the customer, exactly as a pharmacy identifies the patient.
Never bind "customer" to "whoever walked in or paid". The customer is who the record is true of. Identifying that person (patient lookup, owner lookup) is a capture discipline, and it is the same discipline in every vertical.
Ownership and the parent tree
Every entity has exactly one parent, and the parent can be almost anything: a customer, the business, a location, or another entity. That single pointer, allowed to point anywhere, is what makes the model bend to reality.
- Customer owned (rung 2): a vehicle's parent is its owner.
- Business or third party owned (rung 3): a rental van's parent is the business; a landlord's unit's parent is the landlord.
- Nested (a tree): a wheel under a vehicle under a customer; a boiler under a property under a landlord. The tree is how "equipment at an address that a landlord owns" models cleanly without a special case.
- Unowned: a stray brought to a vet has no owner yet, the parent can be null (or the business), and be re-pointed if it is adopted.
- Re-parenting: a car is sold, a pet is adopted, ownership moves. The single pointer is updated. History stays with the entity.
One parent, pointable anywhere, is deliberately simple. If a business ever genuinely needs many owners for one thing (co-owned asset), that becomes a later relationship on top; single parent migrates into it cleanly, the reverse would lose information.
The procedure
For a human or an agent looking at any order, business, or "how do I record this?" question, walk this. First match wins.
Step 1, is there a subject?
Look at the line items. Does any product or service declare a subject_entity_type? If none do, the order is rung 0. Record only transaction facts (notes, status, payment) on the order. Stop.
Step 2, what rung is the subject? Apply the test. Is it context on the person (rung 1), a thing they own (rung 2), or a thing the business or a third party owns (rung 3)?
Step 3, identify the subject, not the payer. The customer on the order is who it is about (the patient, the owner). Whoever pays or presents is payment, not the customer. At rung 2 or 3, resolve the entity from the customer's (or business's) entities of that type: one attaches silently, several prompt, none create.
Step 4, place each activity by what it is true of. Transaction facts (notes, status, money) to the order. Measurements and checks of the subject to the entity (or the customer at rung 1), stamped with the order. Durable traits of the person to the customer.
Step 5, let the pack do the rest. Reminders (service due, vaccine due, refill due) live on the entity so they survive the order and fire on schedule. That is the repeat business engine, and it comes for free once the readings are on the entity.
Worked examples
Each shows the subject, its rung, and where things land.
Auto repair (rung 2)
Subject: the vehicle, owned by the customer. Order: "Brake service" declares vehicle, checkout attaches the customer's Corolla. Readings (brake pad 2.0mm, odometer 84,120) go on the Corolla, stamped with the order. Note "customer approved rotor skim" goes on the order. Next visit: the Corolla shows its brake history and the "service due" reminder has already fired. The payoff is entirely because the reading lived on the car.
Vet (rung 2)
Subject: the pet. "Grooming" and "Vaccination" declare pet; a two pet household prompts for which. Weight and vaccine go on the pet; "nervous around clippers" is a durable trait, so it also goes on the pet, not the order. Vaccine schedule and reminders live on the pet.
Pharmacy (rung 2, with policy)
Subject: the patient (and often a prescription entity under them). The order is against the patient regardless of who collects or pays. Dispensed quantity, refills remaining, interaction checks attach to the prescription. A relative paying is tender; an insurer is a payer. On top of the generic model, pharmacy adds a policy layer (controlled substance logging, record access control, retention), because a prescription carries legal weight a vehicle does not.
Salon / barber (rung 1)
Subject: the customer themselves. subject_entity_type = "customer". No separate entity. Colour formula and hair notes are fields and activities on the customer. The haircut is the order.
Property management (rung 1, or rung 3)
Two valid shapes, pick by need:
- Tenant centric (rung 1): the customer is the tenant. "Unit 4B", lease end, and complaints are fields and activities on the tenant. Monthly rent is the order. Nothing new to build; it is activities on the customer. Right when you only need to know each tenant's unit and log their complaints.
- Landlord centric (rung 3): the customer is the landlord (the property manager's client). The unit is an entity owned by the landlord, referenced by rent orders, and it accumulates maintenance history across tenants. Right only when the unit needs a life independent of who rents it.
Rentals (rung 3)
Subject: your asset (the kayak, the drill). The entity is business owned. Each rental order references it; condition checks and damage notes go on the asset, building a utilization and wear history across every renter. What looked like an ownership problem (the customer does not own the thing) is the feature: per asset history.
HVAC / field service (rung 2, nested)
Subject: equipment at a property. The boiler's parent is the property; the property's parent is the customer. "Filter due", "last serviced", warranty window live on the equipment. The tree carries "a landlord's equipment across ten addresses" with no special case.
Device repair (rung 2)
Subject: the device, owned by the customer. Like auto. A trade in is the one twist: the device becomes your stock, so its parent moves from the customer to the business (rung 2 to rung 3) at the moment of trade in.
Gym (rung 1)
Subject: the member (the customer). Check ins, class packs, and progress are activities on the customer; the membership itself is an access grant. No separate entity needed.
Restaurant / retail (rung 0)
No subject. The model correctly does nothing: no prompt at checkout, no entity, no card. Notes, status, and payment on the order, and that is all. Emptiness here is correct, not a gap.
Anti-patterns
The recurring mistakes, and the fix for each.
- Parenting the subject on the order. It silos the thing to one sale and destroys the history. Fix: parent on the owner (customer, business, location); let the order reference it.
- Putting readings on the order. Same silo, one level down. Fix: readings go on the entity (or customer), stamped with the order.
- Modelling everything as an entity. Reaching for rung 2 when rung 1 will do adds a phantom object. Fix: if the subject is the person or a simple fact about them, keep it on the customer.
- Binding "customer" to who paid or walked in. Invents ownership problems that do not exist. Fix: the customer is who the record is against; payment is a separate axis.
- Letting quantity imply the subject. "Brake service x2" is not "two vehicles". Fix: assign the subject per line, explicitly; quantity is just quantity.
- Free text where a type belongs. A note that says "odometer 84120" is invisible to charts, reminders, and Reesa. Fix: record it as a reading so the platform can act on it.
- Over modelling retail. A coffee shop does not need entities. Fix: rung 0, move on.
Quick reference
The ladder
0 no subject retail, food
1 context on the customer salon, gym, tenant + unit + complaints
2 a customer's owned entity vehicle, pet, device, patient
3 a business/third-party entity rental asset, landlord's unit, shared kitWhere activities attach
transaction fact (note, status, money) → order
measurement/check of the subject → entity (stamped with the order) [rung 2/3]
→ customer [rung 1]
durable trait of the person → customer
a reminder about the subject → entity (so it outlives the order)
a link to the subject → order (references the entity)The two axes to keep separate
who the order is against = the customer / patient / owner → owns the subject, holds the records
who tenders the payment = cash, card, relative, insurer → a payment concern, not the customerWhere this is still hardening
Per line multiplicity is now solved. One order can be about several subjects, each line can name its own (a fleet invoice attributes and subtotals per vehicle), and the reference is a reconciled set rather than a single pointer. Picking which line is about which subject is still an explicit choice, not something quantity can imply, but the model and the surfaces for it exist.
Two layers are deliberately scoped, not yet built:
- Per type policy. A
prescriptionorpatientcarries obligations (controlled substance logs, record access, retention) that avehicledoes not. That is an additive policy layer on the generic registry, delivered by the vertical's pack, not something the base engine assumes. - Analytics across subjects. One subject's history is instant; aggregate questions ("average odometer across the fleet", "revenue per vehicle") are not yet a first-class query. The reading metadata above is deliberately rich enough that a reporting layer can be generated from it later, but that layer is not built.
Everything else on this page is the stable model: a subject declared by the service, an entity owned by whoever actually owns it, activities placed by what they are true of, and a memory that compounds across every visit.
Business standing
How to read the sell-through projection on your Inventory page: potential revenue, cost, estimated profit, the realistic-vs-best-case range, at-risk stock, and what 'nothing sells this yet' means.
Overview
Dozens of real businesses modelled end to end, grouped by family. Pick the group closest to the business — each page shows what moves, the exact setup, and the trap to avoid.