# Reports & Metrics

Sales, products, promotions, trends, operations, alerts and per-order logs.

# Reports and Metrics: which to use

> **Audience:** managers and analysts reading performance data, and operations staff investigating a specific order.
> **You need:** *Sales reports* for Reports, *Metrics* for Metrics. They are separate permissions.

The console has two data areas, and picking the right one saves a lot of time.

| | Reports | Metrics |
|---|---|---|
| Answers | "How did we do?" | "What happened to this order?" |
| Shape | Aggregated — totals, breakdowns, trends | Per-order — logs, timelines |
| Period | A business date or a date range | Recent activity |
| Typical reader | Management, analysts, area managers | Support, operations, anyone investigating |

If you are looking at numbers, you want Reports. If you are looking for one order's history, you want Metrics.

## What's in Reports

| Report | Answers |
|---|---|
| **Sales** | Revenue over the period |
| **Product sales** | Which articles sold, grouped by family |
| **Promotions** | How much each promotion was used |
| [Sales by trend](/books/console-yF7/page/sales-by-trend) | Monday-to-Sunday pattern, by category |
| **Operations** | Live-ish operational picture: order states, staff on shift, load over the day, individual orders |
| [Operational alerts](/books/console-yF7/page/operational-alerts) | Stores currently outside a threshold you set |

## What's in Metrics

| View | Answers |
|---|---|
| **Order logs** | Which orders had activity, and what was done to them |
| **Order timeline** | The full sequence of actions on one order |
| [Archived alarms](/books/console-yF7/page/archived-alarms) | Alarms already dealt with |

## Permissions

| To do this | You need |
|---|---|
| Open any report | *Sales reports* |
| Open order logs and timelines | *Metrics* |
| Export from Metrics | *Metrics — export*, a separate and higher permission |
| See archived alarms | *Archived alarms* |

`report_viewer` is the role built for this: reports, metrics and store visibility, nothing else. It combines well with an operational role — see [Common role combinations](/books/console-yF7/page/common-role-combinations).

## Everything is scoped

Every figure is filtered to your scope before you see it. Two colleagues running the same report on the same day can legitimately get different totals, because they can see different stores or brands.

This is the single most common "the report is wrong" report, and it usually isn't. See [How scope works in practice](/books/console-yF7/page/how-scope-works-in-practice) before investigating further.

## The pages in this chapter

| Topic | Page |
|---|---|
| Filters, dates and the dashboard | [Filters, dates and favourites](/books/console-yF7/page/filters-dates-and-favourites) |
| Revenue | [Sales report](/books/console-yF7/page/sales-report) |
| Articles sold | [Product sales report](/books/console-yF7/page/product-sales-report) |
| Promotion usage | [Promotions report](/books/console-yF7/page/promotions-report) |
| Weekly patterns | [Sales by trend](/books/console-yF7/page/sales-by-trend) |
| The operations screen | [Operations report](/books/console-yF7/page/operations-report) |
| Threshold-based store alerts | [Operational alerts](/books/console-yF7/page/operational-alerts) |
| One order's history | [Order logs and timelines](/books/console-yF7/page/order-logs-and-timelines) |
| Getting data out | [Exporting data](/books/console-yF7/page/exporting-data) |

# Filters, dates and favourites

> **You need:** *Sales reports*.

Every report is driven by the same filter set. Understanding it once covers the whole chapter.

## The filters

| Filter | Required? | Notes |
|---|---|---|
| **Brand** | Yes, on most reports | Reports are built per brand. With one brand it may be preselected |
| **Stores** | No | Empty means every store within your scope |
| **Sources** | No | Web, app, aggregators. Only applies where source filtering is active |
| **Business date** | Yes | The day the report covers |
| **End date** | Only in range mode | Turns one day into a period |
| **Time window** | No | Narrows to part of the day |

The available values are loaded from your own scope, so the store list is what you can see, not everything that exists.

## Day mode versus range mode

- **Day** — one business date. The default for operational questions.
- **Range** — a start and an end date, for a week, a month, a comparison.

Switching modes changes what some reports mean. A 15-day chart in range mode anchors on the **end** date, not the start.

## Business date is not calendar date

This is the one that catches people out.

A business date covers a trading day, which for late-night service runs past midnight. An order placed at 01:30 on Saturday usually belongs to **Friday's** business date.

So "yesterday's sales" means yesterday's *business date*, not the calendar day. When a total looks like it's missing the late evening, check which date the late-night orders landed on.

> Two reports disagreeing by roughly one evening's trade is almost always this, not a fault.

## The time window

Start and end times narrow a report to part of the day — the lunch service, the evening peak.

The window applies **within** each business date in your range. Setting 19:00–23:00 over a week gives you seven evenings, not one continuous stretch.

## Favourites and the dashboard

The dashboard pulls its widgets in one batch, so it loads as a single view rather than piece by piece.

Use it for the numbers you check daily. For anything you need to slice, go to the report itself — the dashboard is a summary, not a filtered view.

## Getting a report you can trust

1. **Set the brand first.** Most reports need it, and changing it later resets other choices.
2. **Confirm the mode**, day or range.
3. **Set the business date**, remembering it is not the calendar date.
4. **Add stores and sources only if you mean to narrow.** Empty means "everything I can see", which is usually what you want.
5. **Check the store count** against what you expect. Fewer stores than expected is a scope question — see [How scope works in practice](/books/console-yF7/page/how-scope-works-in-practice).

## Related pages

- [Reports and Metrics: which to use](/books/console-yF7/page/reports-and-metrics-which-to-use) — picking the right area
- [Operations report](/books/console-yF7/page/operations-report) — the most filter-sensitive screen
- [Exporting data](/books/console-yF7/page/exporting-data) — taking figures out of the console

# Sales report

> **You need:** *Sales reports*.

The sales report gives revenue over the period you select, filtered to your scope.

## Reading it

Set the brand, the mode and the business date — see [Filters, dates and favourites](/books/console-yF7/page/filters-dates-and-favourites) — and the report covers exactly that period for the stores you can see.

In day mode it answers "how did we do yesterday". In range mode it answers "how did we do last month", and is the right shape for comparing periods.

## Before comparing two periods

Comparisons go wrong for mundane reasons more often than interesting ones:

| Check | Why |
|---|---|
| Same store set? | Adding or closing a store changes the total without changing performance |
| Same sources? | An aggregator switched on mid-period moves volume without creating it |
| Comparable days? | Four weekends against five is a 20% swing on its own |
| Same time window? | A window applied to one period and not the other isn't a comparison |

## When the total looks wrong

1. **Business date, not calendar date.** Late-night trade lands on the previous business date. This explains most "missing evening" reports — see [Filters, dates and favourites](/books/console-yF7/page/filters-dates-and-favourites).
2. **Your scope.** You see your stores, not all stores. A colleague's different total may be correct for both of you — see [How scope works in practice](/books/console-yF7/page/how-scope-works-in-practice).
3. **Cancellations.** A high cancellation rate suppresses revenue while order counts stay high — check [Operational alerts](/books/console-yF7/page/operational-alerts).

## Related pages

- [Product sales report](/books/console-yF7/page/product-sales-report) — the same period broken down by article
- [Promotions report](/books/console-yF7/page/promotions-report) — how much was given away over that period
- [Sales by trend](/books/console-yF7/page/sales-by-trend) — the weekly pattern behind the total

# Product sales report

> **You need:** *Sales reports*.

Product sales shows what actually sold, by article, grouped into families.

## What it's for

The sales total tells you the revenue. This tells you what produced it — which articles moved, and which families carry the period.

Typical questions it answers:

- Which articles are worth keeping on the menu?
- Did a new product land, or is it sitting?
- Has the family mix shifted since last month?

## Reading the grouping

Articles roll up into families, so you can read it at either level: the family view for the shape of the menu, the article view for individual decisions.

A family that looks flat can hide one article growing while another falls. Open the family before concluding nothing changed.

## Pairing it with other reports

| Question | Also look at |
|---|---|
| Did discounting drive these sales? | [Promotions report](/books/console-yF7/page/promotions-report) |
| Is this a weekday or weekend product? | [Sales by trend](/books/console-yF7/page/sales-by-trend) |
| Did the revenue actually land? | [Sales report](/books/console-yF7/page/sales-report) |

An article that sells well only alongside heavy promotion is a different business case from one that sells at full price. The two reports together say which you have.

## Scope applies here too

Figures cover the stores within your scope for the period selected. A product that looks absent may simply not be sold by the stores you can see — see [How scope works in practice](/books/console-yF7/page/how-scope-works-in-practice).

# Promotions report

> **You need:** *Sales reports*.

The promotions report shows usage grouped by promotion code — how often each was applied over the period.

## What it's for

It answers the question marketing actually needs: **which promotions are being used**, and therefore which are worth repeating.

Read alongside [Sales report](/books/console-yF7/page/sales-report) and [Product sales report](/books/console-yF7/page/product-sales-report), it also answers the harder question — whether the promotion brought in business or discounted business that was coming anyway.

## Reading it

Usage is grouped by code, so a campaign appears as the code customers entered. If you ran several codes for one campaign, you will see them separately; group them yourself, or run future campaigns as one campaign with multiple coupons so they stay together — see [Promotional codes](/books/console-yF7/page/promotional-codes).

## Questions worth asking of it

| Pattern | What it usually means |
|---|---|
| High usage, flat sales | Discounting business you already had |
| Low usage, wide distribution | The code isn't reaching people, or isn't attractive |
| Usage concentrated in a few stores | Local awareness, or the offer only applies there |
| Usage stops abruptly mid-period | The campaign hit its end date, or was expired — check [Promotional codes](/books/console-yF7/page/promotional-codes) |

## Zero usage is a finding

A promotion with no usage is worth investigating before repeating it. The usual causes are all fixable: the campaign was not live for those stores, the dates or valid times excluded the trading period, or the codes were never distributed.

The [Promotional codes](/books/console-yF7/page/promotional-codes) page lists the checks in order.

## Related pages

- [Promotional codes](/books/console-yF7/page/promotional-codes) — creating, expiring and troubleshooting campaigns
- [Personal promotions](/books/console-yF7/page/personal-promotions) — offers granted to specific customers
- [Sales report](/books/console-yF7/page/sales-report) — whether the revenue moved

# Sales by trend

> **You need:** *Sales reports*.

Sales by trend lays the period out as a Monday-to-Sunday matrix, broken down by category.

## What it's for

Totals hide the shape of a week. This report shows it: which days carry the business, which are quiet, and whether that differs by category.

It is the report to use for decisions that are **about the week** rather than about the total — staffing, opening hours, when to run a promotion.

## Reading the matrix

Rows are categories, columns are days of the week. The useful reading is across a row: a category that is flat all week behaves differently from one that spikes at the weekend.

Over a multi-week range each weekday aggregates all its occurrences, so a four-week range gives you four Mondays combined. That is what makes the pattern readable rather than noisy.

## Watch the range length

An uneven range distorts the matrix. Thirty days contains five of some weekdays and four of others, so those columns are not comparable.

> Use whole weeks when you want to compare days. Use any range you like when you only want each day's total.

## What to do with it

| Pattern | Worth considering |
|---|---|
| One weekday consistently quiet | A promotion aimed at that day, or reduced staffing |
| Weekend-heavy in one category only | Menu or pricing specific to those days |
| A day that changed shape recently | Compare against an earlier range before assuming a trend |

## Related pages

- [Sales report](/books/console-yF7/page/sales-report) — the total behind the pattern
- [Product sales report](/books/console-yF7/page/product-sales-report) — which articles drive each category
- [Operations report](/books/console-yF7/page/operations-report) — the shape of a single day, hour by hour

# Operations report

> **You need:** *Sales reports*.

The operations report is the widest screen in the chapter. It answers "what is happening operationally", where the other reports answer "what did we earn".

## Order status and breakdown

Counters for where orders currently stand, plus a full breakdown by order type — delivery, pickup, takeaway and dine-in — each split into time buckets.

The time buckets are the useful part. A high total tells you it is busy; the buckets tell you whether orders are moving or piling up in the slow end.

## Staff on shift

Who is currently active, grouped by job position, alongside the status of every store that is open.

An employee counts as **active** when they have clocked in for the shift and not yet clocked out. So this is a live view of who is actually on, not who was rostered.

Read it next to the order counters: heavy volume against thin staffing is the situation worth acting on, and neither number says it alone.

> Requires a brand. Stores are optional, and empty means every store in your scope.

## The 15-day chart

A time series of total orders in fixed 15-minute slots, for the reference date and the previous 14 business days.

The reference date is the business date in day mode, and the **end** date in range mode — worth knowing before you conclude the chart is showing the wrong period.

Fourteen days of history is what makes today readable. A slow hour only means something against how that hour normally looks.

## Orders list, count and detail

Three views of the same underlying set:

| View | Use it for |
|---|---|
| **Count** | How many orders match the filters, without loading them |
| **List** | The orders themselves |
| **Detail** | Line-level detail of one order |

Run the count first when you are unsure how wide your filters are — it is much faster than loading a list you are about to discard.

Order detail is scoped per order, so you can only open orders for stores, brands and sources within your scope.

## Store configuration changelog

The most recent configuration change per store.

This is the report that answers "did something change?" when a store's behaviour shifts. Before investigating a store that has started missing its promised times, check whether its settings moved — see [Store delivery settings](/books/console-yF7/page/store-delivery-settings).

## Related pages

- [Operational alerts](/books/console-yF7/page/operational-alerts) — the threshold-based version of this screen
- [Filters, dates and favourites](/books/console-yF7/page/filters-dates-and-favourites) — business date, modes and time windows
- [The order board](/books/console-yF7/page/the-order-board) — the live Hub view, for acting rather than reading

# Operational alerts

> **You need:** *Sales reports*.

Three reports that return only the stores currently outside a threshold you set. Where the operations report shows everything, these show you only what needs attention.

## The three

| Alert | Flags a store when | Default threshold |
|---|---|---|
| **Delivery load** | Pending deliveries per active driver exceed the threshold | 2 |
| **Cancellations** | The share of valid orders falls below the threshold | 90% |
| **On-time** | On-time percentage is below the threshold **and** average delivery time exceeds the maximum | 80% and 60 min |

Each threshold is a parameter you pass when running the report, not a saved setting. Change it and re-run to widen or narrow what comes back.

## The on-time alert needs both conditions

This is the one people misread. A store is only flagged when it is **both** below the on-time percentage **and** above the average-time limit.

That is deliberate. A store missing its target by a little while still delivering quickly is a different problem from one that is slow across the board — and only the second is worth interrupting someone for.

If you want the looser view, raise the maximum-minutes value rather than lowering the percentage.

## These are not the Hub alarms

Easy to confuse, genuinely different:

| | Operational alerts | Branch alarms |
|---|---|---|
| Where | Reports | Hub |
| Threshold | Passed per run, by you | Configured chain-wide |
| Lifecycle | Recomputed each time you run it | Raised, then archived |
| Use | Reviewing a period | Acting during service |

Use these when reviewing; use [Branch alarms](/books/console-yF7/page/branch-alarms) when running the shift.

## A workflow that works

1. Run all three at their defaults for yesterday.
2. For any store that appears, open the [Operations report](/books/console-yF7/page/operations-report) filtered to it.
3. Check the **store configuration changelog** — did something change?
4. If several stores appear together, suspect a shared cause before working through them one at a time.
5. If the same store appears every day, the threshold is describing normal for that store. Either fix the store or accept it — a permanently-flagged store is noise.

## Related pages

- [Operations report](/books/console-yF7/page/operations-report) — the full picture behind an alert
- [Branch alarms](/books/console-yF7/page/branch-alarms) — the live, chain-wide equivalent
- [Alarm settings](/books/console-yF7/page/alarm-settings) — where the Hub's thresholds are configured
- [Store delivery settings](/books/console-yF7/page/store-delivery-settings) — the tolerances a store is measured against

# Order logs and timelines

> **You need:** *Metrics*.

Order logs answer "what happened to this order" — the question Reports cannot answer, because Reports aggregates.

## The paginated list

Orders that have recorded activity, filtered by store, brand and source within your scope. Use it to find the order you care about, then open its timeline.

## The timeline

The full sequence of actions recorded against one order, in order.

An order is identified by store, ticket number and source together — a ticket number alone is not unique across stores. See [The order board](/books/console-yF7/page/the-order-board) for why.

The timeline is what answers:

| Question | What to look for |
|---|---|
| Who handled this, and when? | The sequence of actions and their timestamps |
| Was it reassigned? | Assignment changes, and whether a person or the dispatcher made them |
| Why was it late? | Where the gap actually sits — kitchen, pickup, or on the road |
| Did someone force or cancel it? | Those actions appear here with who did them |

## Using it in an investigation

1. **Get the identifiers.** Store, ticket number, source.
2. **Open the timeline.** Read it end to end before forming a theory — the interesting event is often earlier than expected.
3. **Find the gap.** Look for the long pause rather than the last event.
4. **Cross-check the dispatcher** if the gap is in assignment — a Request ID from that period ties it to a specific run. See [Reporting a dispatcher issue](/books/console-yF7/page/reporting-a-dispatcher-issue).

## Metrics versus the Hub

Both show orders, for different purposes:

| | Metrics | Hub |
|---|---|---|
| Time frame | What already happened | What is happening now |
| Purpose | Explain | Act |
| Can you change anything? | No | Yes |

If the order is still live and needs intervention, work in the Hub — see [The order board](/books/console-yF7/page/the-order-board). If it is finished and needs explaining, work here.

## Related pages

- [Exporting data](/books/console-yF7/page/exporting-data) — taking this out of the console
- [Archived alarms](/books/console-yF7/page/archived-alarms) — the alarm-side history
- [The order board](/books/console-yF7/page/the-order-board) — the live equivalent

# Exporting data

> **You need:** *Metrics — export*. This is a **separate, higher** permission than *Metrics*, and is normally held by `admin` rather than by everyone who can read metrics.

Two things can be exported: **order action logs** and **archived alarms**. Both come out as data files for analysis outside the console.

## Why export is a separate permission

Reading inside the console is scoped. Every screen filters to the stores, brands and sources you are allowed to see, every time you open it.

**An exported file is a snapshot with that protection removed.** Once it is a file on someone's laptop, it can be opened, forwarded and combined by anyone, regardless of what they could see in the console. The scope applied at export time; it does not travel with the file.

That is why export sits behind its own permission, and why it is worth thinking about before using it.

## Before exporting

| Ask | Because |
|---|---|
| Do I need the raw rows, or an answer? | A conclusion shared in a message is safer and usually more useful than a spreadsheet |
| Can the report answer it instead? | [Reports and Metrics: which to use](/books/console-yF7/page/reports-and-metrics-which-to-use) — aggregated reports often answer the question without raw data |
| Who will end up with this file? | Assume everyone the recipient works with |
| Does it need customer data? | Narrow the filters before exporting, not after |

## Exporting

1. Filter down to what you actually need — the export honours your filters and your scope.
2. Export.
3. Store it somewhere appropriate, and delete it when the analysis is done.

Narrow filters are the main control you have. An export of one store for one day is a very different object from an export of the whole chain for a month.

## What you get

The export reflects exactly what you could see when you ran it. It is not live — reopening the file a week later shows the state at export time, not now.

For anything recurring, re-export rather than reusing an old file, and take the answer from the console where you can.

## Related pages

- [Order logs and timelines](/books/console-yF7/page/order-logs-and-timelines) — what is being exported
- [Archived alarms](/books/console-yF7/page/archived-alarms) — the other exportable history
- [How scope works in practice](/books/console-yF7/page/how-scope-works-in-practice) — what scope does, and what it stops doing at export