T03: Manual Entry
Capture a monthly target through a form, then spread it across days using the period's real length.
What you will build: a monthly production target entered by hand, and a daily target derived from it correctly.
Time: about 25 minutes.
You need: T02 completed, with Bottles Daily producing values.
Step 1 — Create the target measure#
Some numbers exist nowhere except in somebody's head or a spreadsheet. A production target is the classic case.
Under Production, create a metric called Targets, and in it:
| Field | Value |
|---|---|
| Name | Production Target Monthly |
| Retrieval type | Manually entered |
| Interval | Month(s) |
| Unit | bottles |
| Format | #,##0 |
No connection and no tag — there is no source system.
The interval matters. The target is agreed monthly, so the measure is monthly. Choosing the wrong interval here forces awkward workarounds later.
Step 2 — Build a form#
A manual entry measure needs somewhere for a person to type. That is a form — a chart type you can enter data into.
In the Reports view:
- Create a report folder called
Production Reports. - Create a Time Based Form with the Monthly constructor.
- Drop
Production Target Monthlyonto it. - Create a dashboard called
Production Targetsand place the form on it.
Deploy the server if it is not already deployed.
Step 3 — Enter a value#
Open the dashboard in the browser and type a target into the current month. Something plausible — say 2,400,000 bottles.
Save it, and confirm the value appears on the measure in Flow Config.
Only manual cells are editable. If you add Bottles Daily to the same form it will display but not accept input. Infohub will not let a person overwrite a value the engine calculates, because the next calculation pass would discard it.
That is often useful: a form showing last month's actual (read-only) beside this month's target (editable) gives the person entering it the context to set it sensibly.
Step 4 — The problem#
You have a monthly target. Your reporting is daily. You need a daily target to compare against Bottles Daily.
The instinct is to add a daily measure that aggregates from the monthly one. That does not work — aggregation goes up the interval chain, never down.
Step 5 — The solution#
A calculated daily measure that divides the monthly target by the number of days in the month.
In Targets, create:
| Field | Value |
|---|---|
| Name | Production Target Daily |
| Retrieval type | Calculated |
| Interval | Day(s) |
| Unit | bottles |
| Format | #,##0 |
| Dependencies | Production Target Monthly |
Expression:
Period.Duration.TotalDays == 0 ? 0
: Measure_<monthlyTargetId>.Value / Period.Duration.TotalDays
Replace <monthlyTargetId> with the actual measure ID — adding the dependency is what creates the Measure_<id> symbol.
Step 6 — Why Period.Duration.TotalDays#
This is the point of the tutorial.
You could divide by 30. It would be wrong in seven months of the year, and wrong by 7% in February.
Period.Duration.TotalDays asks the period how long it actually is. February gets 28 or 29, April gets 30, July gets 31 — with no special cases and no leap-year logic.
It also respects your calendar. If your production month is not a calendar month, the duration reflects that too.
The guard is not decoration. Period.Duration.TotalDays == 0 ? 0 : looks unnecessary — how can a period have no length? It costs nothing and it means the calculation can never fail. Every division in Infohub gets a guard, without exception. T04 covers why.
Step 7 — Check it#
Look at Production Target Daily. In a 31-day month with a target of 2,400,000, each day should show about 77,419.
Now change the monthly target on the form and watch the daily values update. Infohub tracks dependencies: the monthly value changed, so everything depending on it recalculates for the affected periods.
Step 8 — Add a lab result#
A second, different manual pattern.
Under a new folder Quality, create a metric Lab with:
| Field | Value |
|---|---|
| Name | Brix |
| Retrieval type | Manually entered |
| Interval | Shift(s) — or Day(s) if you have no shift scheme yet |
| Unit | degBx |
| Format | 0.0 |
Add it to a form so the laboratory can enter a reading per shift.
Then put a limit on it — say 10.5 to 12.5. A limit on a manual measure flags an implausible entry at the moment of entry, which catches the misplaced decimal point before it reaches a monthly report. This is the cheapest validation available in Infohub.
The thing that matters most#
Manual values cannot be regenerated. Every other kind of measure can be rebuilt. A retrieved value comes from the source again; an aggregation and a calculation recompute.
A manually entered value that is deleted is gone. The only copy was the one a person typed, and nobody remembers what last March's target was.
This means bulk deletes, purges, and housekeeping operations that are safe for Retrieved, Aggregated, Calculated, and Replicated measures are not safe for manual ones. Always confirm the scope of a bulk operation excludes them, and make sure your backup retention outlives your purge settings.
What you have learned#
Manual entry is a first-class retrieval type. Once entered, a manual value aggregates, calculates, charts, and alerts exactly like retrieved data.
Choose the interval the data is produced at. Monthly targets are monthly measures.
Aggregation goes up, never down. Spreading a coarse value across finer periods is a calculation.
Ask the period its length. Period.Duration.TotalDays beats a hard-coded number, always.
Limits validate manual entry. For almost no effort.
Manual data is irreplaceable. Treat it accordingly.
Try this before moving on#
Decide what a blank target should mean, and implement it.
Nothing entered means no target — calculations guard and produce no value, so the gap is visible.
Nothing entered means carry the last one forward:
Measure_<id>.Value ?? Measure_<id>[-1].Value
Defensible for a slow-moving reference value. Dangerous for a target, because a stale target silently becomes the current one and nobody notices that planning stopped. The failure mode to avoid is not deciding at all.
Next: T04: Your First Calculation — and the guard that keeps calculations alive.