SeriesPart 38 of Building a property procurement platform on MedusaView the cluster →
Medusa & ArchitectureArticle

One property paid far more for the same item. How do you find it before it becomes a pattern?

How we surface unusual unit prices and replenishment cadence from governed, property-scoped Medusa purchase history.

We Are Souk article cover: One property paid far more for the same item. How do you find it before it becomes a pattern?
Souk EngineeringCommerce architectureAug 2026·11 min read
Key takeaways
  • A procurement team rarely needs more raw order data.
  • Which purchases were unusually expensive?
  • Those questions sound simple, but a conventional ecommerce dashboard does not answer them automatically.
  • For a property-procurement marketplace built with Medusa, we added a governed analytical layer over reconciled purchase history.

The client problem

A procurement team rarely needs more raw order data. It needs to know where to look.

Which purchases were unusually expensive? Is one property paying more than the portfolio norm? Are teams replenishing a product every month or only when something breaks? Has a price difference appeared because the product changed, the supplier changed or the purchasing behaviour changed?

Those questions sound simple, but a conventional ecommerce dashboard does not answer them automatically. Orders are spread across properties, units, vendors and product references. Returns and edits change the history. A high price may be perfectly normal inside one filtered category and exceptional in another. Replenishment cadence is meaningless unless the comparison uses distinct purchase dates for the same relevant scope.

For a property-procurement marketplace built with Medusa, we added a governed analytical layer over reconciled purchase history. Users can ask about unusual purchases or reorder cadence in plain language. The language model identifies the permitted analytical operation; deterministic SQL applies the actual filters, computes the baseline and returns the numbers.

The result is not an AI opinion about whether somebody bought badly. It is a focused signal that helps a buyer investigate the right transactions.

Start with the business question, not the algorithm

“Detect anomalies” is too vague to build.

An unusual purchase can mean an unexpected product, an exceptional quantity, a new supplier, a price far above recent purchases or a transaction outside a property's normal pattern. Each definition produces different results and requires different data.

The implemented analytical contract focuses on unusually high unit prices within the currently filtered purchase-history population. It calculates the average unit price and population standard deviation, then counts rows whose unit price is greater than the average plus two standard deviations.

That definition is deliberately explicit. It does not claim fraud, waste or pricing error. It says: inside the scope you asked about, these unit prices sit far above the baseline formed by the same scoped data.

The buyer can then inspect the product, SKU, property, vendor, order date and price. The system supplies the clue; a person supplies the commercial explanation.

The filter defines what “unusual” means

A price is never unusual in isolation.

A premium replacement part compared with every low-cost consumable in the marketplace will naturally look extreme. That is not useful. The same part compared with its own historical purchases, one category, one vendor or one property can reveal a meaningful deviation.

The purchase-history surface supports explicit filters for product, SKU, vendor, property, unit, building, GL code, category, manufacturer, date and status. An operator can therefore ask questions such as:

  • Which plumbing purchases had unusually high unit prices last quarter?
  • Did any property pay far more for this SKU?
  • What was the highest price from this vendor last month?
  • How often do we reorder this product across the accessible portfolio?

The anomaly baseline is calculated after those filters are applied. It is not a single global number cached for every question.

That choice makes the signal interpretable. The same purchase may be ordinary in a broad portfolio view and exceptional inside a carefully chosen product and date range. Both answers can be correct because they answer different questions.

Reconcile purchase history before analysing it

Analytics inherit the quality of their base rows.

If a report simply sums original cart lines, it can continue counting quantities that were later returned or changed. If an order line was allocated across several units, a naïve join can duplicate spend. If categories or vendors are joined without care, one purchase can appear several times.

The analytical layer starts from the platform's reconciled Purchase History representation. It connects organisation orders, properties, line items, products, vendors, categories, manufacturers, GL allocations and units. Allocation slots and the current order-item quantities determine the displayed rows after edits and returns.

This is why anomaly detection belongs above a governed data model, not beside a raw orders table. Before asking whether a price is exceptional, the platform needs a stable definition of one analysed purchase row and the commercial context attached to it.

The claim remains appropriately bounded: this is a commerce analytics surface, not a general accounting ledger. It reflects the purchase-history contract used by the application.

Let language choose an allowed question, not write SQL

Natural language is useful because operators do not always know the dashboard vocabulary.

They may ask, “Are we paying too much for filters?” or “How often do we reorder smoke detectors?” The system needs to translate that intent into products, SKUs, dates, scope and metrics.

Giving a model unrestricted database access would make that convenience too powerful. Instead, the model produces a structured plan from a closed schema. The plan can select allowlisted filters, aggregations, breakdown dimensions, sorting, limits and either current-property or all-accessible scope. It cannot submit arbitrary SQL.

Deterministic code then hardens common intents. Words such as “anomaly”, “outlier” or “unusually large” add the anomaly count and maximum unit-price operations. A request for reorder frequency adds the cadence metric. Relative dates are converted into explicit ranges.

The backend, not the model, executes the plan and computes the result. The final answer is assembled from those calculated analytics.

AI makes the interface flexible. It does not become the source of the number.

Keep every question inside the caller's property perimeter

A portfolio insight must not become a permission bypass.

Before any analytical filter runs, the backend resolves which property IDs the authenticated organisation member may access. Organisation-level users can work across the appropriate portfolio. Property managers and supervisors remain restricted to managed properties. Buyer-side members use their assigned-property relationships.

A natural-language request can narrow that set but cannot expand it. Asking for “all properties” does not grant access to properties outside the computed perimeter. A property name supplied by the user remains subject to the same intersection.

The base SQL is organisation-scoped before aggregations are calculated. This is important because even a single metric can leak information. An average, maximum or anomaly count from an inaccessible property is still inaccessible data, even when no individual order row is displayed.

The conversational layer changes how somebody asks. It does not change what that person is allowed to know.

Explain the anomaly as a lead, not a verdict

The statistical rule is useful precisely because it is modest.

A row above average plus two population standard deviations is worth inspecting. It is not automatically wrong. The product may have changed specification. The supplier may have included a service. The property may have needed an emergency delivery. A very small filtered sample may also provide a weak baseline.

We therefore present anomaly output with surrounding purchase context and complementary metrics such as maximum and average unit price. The operator can compare actual transactions rather than receiving a red badge that says “bad purchase”.

This avoids two common product mistakes. The first is marketing a simple threshold as intelligent fraud detection. The second is hiding the definition so users cannot understand why a transaction was highlighted.

An effective procurement signal should be reproducible: apply the same scope, filters and equation, and the same rows should qualify. Investigation can then focus on commercial meaning rather than arguing with a black box.

Calculate replenishment cadence from distinct order dates

Price deviation answers one question. Cadence answers another: how regularly does this organisation buy the filtered product or category?

The implemented metric takes the distinct purchase dates inside the scoped result, orders them chronologically, calculates the day intervals between consecutive dates and averages those intervals.

Using distinct dates avoids treating several relevant lines in one order day as several replenishment events. Applying the scope first lets the same operation answer different questions: cadence for one SKU, one property, one category, one vendor or the accessible portfolio.

If there is only one purchase date, there is no meaningful interval to average. A returned zero in the analytical contract should be understood as insufficient observed intervals, not as “reordered on the same day forever”. The user-facing explanation needs that context.

Cadence is descriptive, not predictive. It shows the rhythm present in retained purchase history. It does not promise the next order date or know whether future demand will change.

Use cadence to ask better operational questions

Even a descriptive cadence can unlock useful conversations.

If several properties reorder the same consumable at very different intervals, procurement can ask whether stock policies differ or whether one location buys in inefficient quantities. If a regularly purchased item suddenly disappears from the recent period, operations can check whether the product was substituted, the supplier changed or purchasing moved outside the platform.

Combined with unit price, cadence can expose a negotiation opportunity. A stable repeat purchase may justify a contracted assortment or volume discussion. An irregular emergency pattern may suggest that planned replenishment would reduce urgency.

The system does not assert those conclusions. It makes the underlying pattern easy to retrieve across dimensions already present in purchase history.

That is more valuable than another static chart. A buyer can start broad, see a signal and continue with “break that down by property” or “show the highest-priced purchases from this vendor” without commissioning a new report.

Preserve conversational context without contaminating the next question

Procurement analysis is iterative.

A user might ask for unusual plumbing purchases last quarter, then continue with “and by property?” The planner can carry the relevant product, date and scope context into that follow-up.

But context can also become dangerous. If the next question starts a new product or vendor subject, stale table filters should not silently remain active. Guard logic therefore inherits current-view filters only when the latest question explicitly refers to the table, its filters or an obvious continuation. A new subject drops stale context.

This is a subtle part of making conversational analytics trustworthy. A mathematically correct answer with an invisible leftover filter is still the wrong answer.

The interface should make the interpreted scope visible: what period, properties, products and vendors were included. Users can then refine the question with confidence rather than guessing what the assistant remembered.

Why Medusa was the right foundation

Medusa supplied the transactional order lifecycle. The client needed portfolio-specific intelligence over property, allocation, vendor and catalogue dimensions that a standard storefront does not automatically provide.

Because the commerce engine was extensible, we could build a purchase-history projection that reflects edits, returns and allocations, then expose governed analytics over it. The order system remains the source of commerce events. The analytical layer defines how those events become questions a property operator can use.

We added the dimensions and controls required by the business: property access, unit and GL context, vendor and category enrichment, an allowlisted query plan, deterministic metrics and conversational follow-ups.

The architectural choice serves a practical outcome. A buyer can move from “something feels expensive” to a scoped set of transactions without exporting the order database or waiting for a bespoke business-intelligence report.

A practical checklist for purchasing signals

Before surfacing anomalies or cadence, define:

  1. What is one purchase-history row after edits and returns?
  2. How are allocation joins prevented from duplicating spend?
  3. Which properties may the caller analyse?
  4. Which filters create the statistical baseline?
  5. Is the threshold definition visible and reproducible?
  6. Does an anomaly mean “investigate” rather than “wrong”?
  7. Which price field is compared?
  8. How are small samples explained?
  9. Are cadence intervals based on distinct order dates?
  10. What does cadence return when fewer than two dates exist?
  11. Can a language model generate only an allowlisted plan?
  12. Does the backend compute every metric?
  13. Can follow-up questions inherit useful context?
  14. Can a new subject discard stale filters?
  15. Can users inspect the purchases behind the aggregate?

The quality of the insight depends less on conversational polish than on these contracts.

The broader lesson

Procurement teams do not need AI to declare that a purchase was bad.

They need a fast, defensible way to find transactions that deserve attention and patterns that deserve a conversation.

For this marketplace, natural language selects a governed analytical plan. Property permissions bound the data before calculation. Reconciled purchase history supplies the commercial grain. Deterministic SQL identifies unit prices above an explicit filtered baseline and computes average intervals between distinct purchase dates.

The operator gets an intelligible signal with the transactions and scope needed to investigate it. No arbitrary SQL, no invented model arithmetic and no claim that a statistical outlier proves wrongdoing.

That is how conversational analytics becomes useful in commerce: not by replacing procurement judgement, but by helping that judgement reach the right evidence sooner.

Read next
Keep the useful ideas coming

One practical commerce field note at a time.

Join the WeAreSouk journal for grounded stories about Medusa, Shopify, AI, integrations and the systems behind serious commerce.

Working on a similar problem?Bring us the business constraint. We’ll help map the system behind it.Talk to Souk →
Souk AI · online now

Turn the article into an implementation plan.

Ask how this applies to your store, your stack, or your current bottleneck.

01 Describe your current setup.02 Name the workflow or signal that feels unreliable.03 Get a practical first architecture back.
I can help map this article to your stack. Tell me what you sell, what platform you use, and where the medusa & architecture question hurts.
Continue the cluster

Building a property procurement platform on Medusa

Start a conversation

Tell us what commerce needs to do for your business.

No scheduling maze. Send the context, the constraint or the idea. We will read it and come back to you directly.