# lunch-order-report-summary Specification

## Purpose
Defines the totals (people, orders, amount) and row ordering returned by the admin lunch order report, so the Statistics page can show figures for the selected filters across all pages.
## Requirements

### Requirement: Paginated report includes a summary
When `GET /api/v1/admin/lunch-orders/report` is called with `limit`, the response SHALL include a `summary` object with `total_people`, `total_orders` and `total_amount`, alongside the existing pagination fields (`data`, `total`, `current_page`, `last_page`, ...), which SHALL stay unchanged.

#### Scenario: Summary returned with paginated report
- **WHEN** an admin calls the report with `limit=10`
- **THEN** the response contains `summary.total_people`, `summary.total_orders` and `summary.total_amount`, and `data` still holds the per-employee rows for the requested page

### Requirement: Summary covers all filtered rows, not only the current page
The `summary` SHALL be computed over every row matching the request's filters (`from`, `to`, `company_id`, `department_id`, `q`, `company_mode`), independent of `limit` and `page`:
- `total_people` SHALL equal the number of employees in the report (equal to the pagination `total`).
- `total_orders` SHALL equal the sum of `number_orders` over those employees.
- `total_amount` SHALL equal the sum of `total_amount` over those employees, i.e. the sum of the recorded `lunch_orders.price` of active orders, with orders whose price is null counted as 0.

#### Scenario: Totals span multiple pages
- **WHEN** 25 employees match the filters, with 60 active orders totalling 2,100,000, and the admin requests `limit=10&page=2`
- **THEN** `summary` is `{ total_people: 25, total_orders: 60, total_amount: 2100000 }`

#### Scenario: Filters narrow the summary
- **WHEN** the admin adds `department_id` so that only 3 employees with 7 orders totalling 245,000 match
- **THEN** `summary` is `{ total_people: 3, total_orders: 7, total_amount: 245000 }`

#### Scenario: Orders without a recorded price
- **WHEN** an employee in the report has 2 orders priced 35,000 and 1 order with null price
- **THEN** that employee contributes 3 to `total_orders` and 70,000 to `total_amount`

#### Scenario: No matching rows
- **WHEN** no employees match the filters
- **THEN** `data` is empty and `summary` is `{ total_people: 0, total_orders: 0, total_amount: 0 }`

### Requirement: Non-paginated report is unchanged
When the report is called without `limit`, the response SHALL remain the plain array of per-employee rows and SHALL NOT include `summary`.

#### Scenario: Report without limit
- **WHEN** an admin calls the report without `limit`
- **THEN** the response body is an array of per-employee rows with the same fields as before, ordered as described in "Report is sortable by total amount"

### Requirement: Report is sortable by total amount
The report SHALL accept `sort` (only `total_amount`) and `order` (`asc` or `desc`) query parameters, following the `sort`/`order` convention of the other admin lists. Rows SHALL be ordered by `total_amount` in the requested direction, then by `number_orders` descending, then by `account_id` ascending, so that paging is stable. When the parameters are missing or invalid, the report SHALL sort by `total_amount` descending. Sorting SHALL NOT change `summary`.

#### Scenario: Default sort
- **WHEN** an admin calls the report without `sort` and `order`
- **THEN** the employee with the highest `total_amount` comes first

#### Scenario: Ascending
- **WHEN** an admin calls the report with `sort=total_amount&order=asc`
- **THEN** the employee with the lowest `total_amount` comes first, and `summary` is the same as without sorting

#### Scenario: Equal amounts across pages
- **WHEN** several employees have the same `total_amount`
- **THEN** they keep the same relative order on every request, so no row is repeated or skipped between pages
