Workforce command center
A blueprint for an operational planning app rather than a reporting dashboard. Use it when a request asks “where are we short, what will it cost to fix, and what should we do next” over a forecast and a supply of people, vehicles, beds or stock. The example is hospital nurse staffing; adapt the names, keep the shape.
The page has five tabs that share one filter bar (facility, region, unit type, specialty, shift, day):
| Tab | Shows |
|---|---|
| Executive summary | A generated narrative with the top risks; six headline cards; risk by facility; a gap heat map by unit type and day; a 12-week trend; burnout; what changed since last week |
| Risk map | Every unit-shift at risk with census, gap, availability, confidence and the recommended action; net gap by unit; why shifts are at risk; a unit action panel |
| Cost optimiser | Four staffing strategies under a chosen assumption set: cost by source, hours filled by source, cost against fill rate, burnout breaches, a comparison table |
| Ask the business | Stored business questions offered as prompts; each answer is a sentence built from the question’s rows plus the question as a table |
| Action plan | The recommended mix, the plan by facility and by day, and the actions: memo, send, export, follow-up task, push to the planning system, explain assumptions |
Data model
Section titled “Data model”Three fact views at different grains, each joined many-to-one to a units view, which joins to a facilities view, so one filter bar narrows all of them:
- Shifts, one row per unit, day and shift of the planning week: forecast and baseline census, forecast confidence, required hours (census ÷ the unit’s patient-to-nurse ratio × shift length), hours already scheduled by source, the gap and surplus, the capacity each fill source could still offer, a risk score and level, a text risk driver, a text recommended action and its family, the hourly rate of each source, and last week’s forecast of the same shift.
- Scenarios, one row per shift, strategy and assumption set (long format): the hours each strategy takes from the float pool, per diem, overtime and agency, the hours left unfilled, the cost of each, and the resulting burnout and care-risk scores. Compute every strategy and every assumption set in the warehouse; the page switches between them with a selection.
- Outcomes, one row per unit and week of history: required and filled hours by source, missed shifts, agency share, burnout and care-risk scores, premium and total spend.
Add a pipeline view (specialty × region: candidates, credentialed, open requisitions, time to fill, demand trend) and a labour-rates view (source × specialty) for the explainer.
Store in the views, computed in the warehouse: 0/1 flags for each counted state (open, high risk,
surplus, overtime threshold breached), a constant 1 column per fact view, labels that sort in
order (12 Mon, 12 Mon Night, 2026-09-28), and the text columns a reader acts on. The
recommended action is a column, so the layer governs it like any figure.
Semantic layer
Section titled “Semantic layer”- Measures: sums of hours by source, open shifts (gap hours ÷ shift length), counts over the
flags, ratios such as fill-rate risk as
SUM(gap) / SUM(required)and overtime risk asSUM(flag) / SUM(rows), averages of the scores, agency exposure asSUM(gap × agency rate), the change against last week’s forecast asSUM(required) − SUM(prior required); for scenarios, gap fill rate, cost by source, total labour cost, shares of fill by source, burnout breaches. - Pinned headline measures: the executive cards must not move when the cost optimiser switches
scenario or assumption, so their inputs carry a filter: recommended savings is
SUM(cost | scenario = A, assumptions = Base) − SUM(cost | scenario = D, assumptions = Base). See Pin a headline to one slice. - Dimensions: facility, region, unit type, specialty, shift, day, shift slot, risk level, risk driver, recommended action, action family, scenario, assumption, week, pipeline specialty and region, rate source.
- Business questions: one per object family and one per prompt — “Where are we most exposed next week?”, “Why is ICU risk increasing?”, “Which hospitals should receive float capacity first?”, “What is the cheapest way to reach 95% fill?”, “Which facilities are overusing agency labour?”, “Where is demand rising but the pipeline weak?”, “Generate a plan under a labour cap”, “What changed since last week?”. Keep the catalogue in one module that both the commit script and the app read, so a prompt and its stored question cannot drift.
Build every object from those questions as described in Governed objects.
Selection groups
Section titled “Selection groups”mainholds the filter bar and chart clicks.scenariosmirrorsmainand adds the chosen assumption set. Shift and day live on both the shifts and the scenarios view, so mirror those two selections onto the scenarios view’s columns; see Mirror a group onto another view.planmirrorsmainand adds the assumption set and the chosen strategy.answersmirrorsmainfor the prompt answers.
A click on a unit name in the risk table opens that unit’s action panel instead of filtering; see Use a click to open a detail.
Generated narrative
Section titled “Generated narrative”The executive summary and the action plan are sentences built from governed queries, re-run when the applied selections change: totals, gap by unit type, the highest-risk shifts with their driver and action, the largest surplus, the scenario totals under the chosen assumptions, and the facilities whose agency share runs above the system’s over the last four weeks. Every number is a stored measure; the app only chooses words. Keep the templates explicit about direction and scope (“Next week, Memorial Hospital is forecast to be 444 hours short”), name the scope the filters produce, and follow Narrative for placement and markup.
The prompt answers use the same approach: run the stored question’s dimensions and measures as a query, write one sentence per question from its top rows, and mount the question as a table beneath it.
Cost optimiser
Section titled “Cost optimiser”A segmented control for the assumption set writes one selection into the scenarios group. The
four strategy cards, the stacked cost and hours charts, the cost-against-fill scatter, the burnout
chart and the comparison table all re-query from the same rows; nothing is recalculated in the app.
A Use this plan button on a card writes that strategy into the plan group.
Colour each fill source the same everywhere (float, per diem, overtime, agency) with
setColoringType perEachMeasure and setMeasureGraphColor per measure, so a stacked bar’s
segments keep their meaning across tiles and filters.
Action plan
Section titled “Action plan”- Memo and deck. Compose a memo and a short slide deck from the same facts as the narrative; list the scenarios considered with their cost, fill and breaches, and the asks.
- Send, task, push. Choose a recipient and send the plan; create a follow-up task with an owner and a due date; push the chosen strategy to the scheduling system as the working plan.
- Explain assumptions. A dialog that states the rules (how required hours, gaps, the risk score and each strategy’s fill order are defined) and mounts the labour-rates view as a table.
- Persistence. An Astrato App can only read metadata and run queries (see Querying the engine), so approvals, tasks and pushes cannot be written to the warehouse from the page. Keep them in the browser with an audit trail for a demonstration and say so on the page, or post them to a backend you own.
Verify
Section titled “Verify”Beyond the acceptance checks, execute each stored question once after publishing and compare its figures with the cards; switch the assumption set and confirm every scenario object changed and the pinned headline cards did not; filter to one facility and confirm the narrative, the prompt answers and the scenario tiles all narrowed; and open a unit’s action panel to confirm its shifts match the risk table’s rows for that unit.