Sales
A real reptile sale isn't instantaneous. Someone reserves an animal, puts down a deposit, picks up days or weeks later — sometimes the buyer ghosts, sometimes you ship and need an audit trail. Herply models this with one sale record that flows through three statuses: pending, completed, cancelled.
The lifecycle
A sale starts when you take a reservation or sell directly:
- Mark as Reserved (from the animal page) — creates a
pendingsale, sets the animal's state toreserved. Buyer info is on the sale form: name, contact, agreed price, notes. - Mark as Sold — completes the sale (or creates one directly if there was no reservation). Animal goes
inactive / sold, location is cleared. - Cancel Sale — sets the sale to
cancelledand reverts the animal to its previous available state (for_saleornone).
These are the only buttons. The state on the animal is derived from the sale's status — reserved means there's a pending sale, sold means there's a completed one. You don't change the animal's state independently for the sale flow; you act on the sale.
Why cancel reverts instead of deletes
Cancelling a sale never deletes the row. The sale stays in the history with status cancelled so you can answer questions like "did I ever try to sell that animal?" or "who reserved her last year and backed out?". The animal returns to the available pool; the sale becomes a footnote.
For a completed sale (the buyer paid, you delivered, then something went wrong — buyer returns the animal, fraud, accidental "Mark as Sold"), the cancel flow does the same thing: status becomes cancelled, animal becomes active again with state for_sale. The sale row keeps a snapshot of buyer info and price; you don't lose the timeline.
One pending sale per animal
You can't have two pending reservations on the same animal at once. If you reserve to buyer A and they ghost, cancel that reservation before you accept buyer B's — the app refuses if you try to double-reserve.
You can have one pending sale plus several historical completed and cancelled sales. The cumulative history is what makes the audit useful.
Buyer info pre-fill
When you complete a reservation (pending → completed), the form pre-fills buyer name, contact, and price from the reservation. You can still edit anything before saving — the deposit might have come down, the buyer's address changes. Pre-fill saves typing, it doesn't lock anything.
What lives on the sale row
- Animal — the animal being sold.
- Buyer name + contact — free text. Phone, email, Instagram handle, whatever you have.
- Price — currency-agnostic number; format is up to your locale.
- Sale date — when the sale was completed (or when it was cancelled, when applicable).
- Status —
pending,completed,cancelled. - Notes — anything else: shipping carrier, deposit amount, pickup arrangements.
Deposits aren't a separate field yet. When they are, they go on the sale row and only matter while pending.
Where sales surface
- The animal page has a banner showing the current sale (if any), with the status and buttons to act on it.
- The Sales sidebar item lists every sale across the space, filterable by status.
- The public profile of a sold animal does not show buyer info. It does show "this animal is sold" with the date if you prefer that signalling, or you can keep it as a regular profile.
If you want a sale to feel like an instantaneous transaction, just use Mark as Sold directly without a reservation step. The flow collapses to one click.