Recued
Menu
← Back to recipes

Show unbilled hours

by recued-core v2 49 views

Use “Show unbilled hours” in Recued. What you have worked and not yet billed, per task. Hours and entry count come from the store over every matching row; the per-task money breakdown covers the entries fetched, and the card says when those differ.

Complete workflow

Billable Hours 5 pinned recipes

Use Billable Hours in Recued for time tracking, invoicing, freelance, and consulting. It includes 11 built-in actions and 4 ready-to-run workflows. Actions that change data use Recued's approval controls.

You are viewing one recipe in this workflow. Installing it opens the complete pack so its other recipes and background automations arrive together.

Show unbilled hours
This recipe

Use “Show unbilled hours” in Recued. What you have worked and not yet billed, per task. Hours and entry count come from the store over every matching row; the per-task money breakdown covers the entries fetched, and the card says when those differ.

pack:billable-hourstime-trackingboardrecords
by recued-core pinned v2

Use “Open an engagement” in Recued. Record a client and the hourly rate you bill them. Keyed on the label, so re-running with the same one converges instead of opening a second engagement at a different rate.

pack:billable-hourstime-trackingbillablerecords
by recued-core pinned v2

Use “Log hours” in Recued. Record one block of work against an engagement. It uses the connections and settings you choose when you run it.

pack:billable-hourstime-trackingbillablerecords
by recued-core pinned v2

Use “Bill a period” in Recued. Group a period's unbilled billable hours by task, stamp each entry with your invoice reference, and produce invoice lines whose amounts add up to the total. Entries already carrying an invoice reference are left alone, so running it twice cannot charge the same hour twice.

pack:billable-hourstime-trackingbillableinvoicing
by recued-core pinned v3
View pack details, dependencies, and permissions →

Reading it

Unbilled is billable time not yet stamped by Bill a period. That is the number that is worth money to you today.

⚠ Non-billable time is counted separately and is never in the amount. It is shown because knowing how much unbillable work an engagement absorbs is the point of tracking it at all.

⚠ The amount is computed at the engagement's CURRENT rate, not the rate in force when each hour was logged — the rate lives on the engagement, not on the entry. If you raised your rate mid-engagement, this revalues old unbilled hours upward. Open an engagement says how to avoid that: a second engagement.

⚠ Money is rounded once, here, to two decimals. Minutes are stored exactly; nothing accumulates rounding across entries because the conversion happens on the total, not per row.

⛔ This groups by task and rounds per group exactly as bill-period does, so the figure here is the figure you will bill. Rounding once on the grand total instead would make this preview disagree with the invoice by a penny or two — which is worse than either rule on its own, because you would not know which one was wrong.

⛔⛔ THE HOURS AND THE ENTRY COUNT ARE COMPLETE; THE MONEY BREAKDOWN COVERS THE ENTRIES FETCHED. They come from two different places on purpose. The totals are computed by the store over every matching row (entry.unbilled_rollup), so they do not silently shrink when you have more unbilled work than one page holds — which is exactly what a page-derived total used to do, and it was understating money owed. The per-task breakdown still needs the rows themselves, so it shows what the limit fetched.

⚠ When the two disagree the card says so and warns. Raise the limit and re-run to make the amount complete. A quiet smaller number is the failure worth avoiding here: you would invoice it.

How it works 40 steps

Inspect the data fetches, transforms, gates, and output this recipe runs.

Process (40 steps)
■ engagement_id trim
Trim whitespace from setting engagement id
■ id_present compare
Check if engagement id has data
⚠ id_guard guard
Stop if id present equals
◆ engagement recued-core.billable-hours.engagement.get
Get engagement on billable hours
■ found compare
Check if engagement record id has data
⚠ found_guard guard
Stop if found equals
■ engagement_ref template
Generate text from a template
■ period trim
Trim whitespace from setting period
■ by_period compare
Check if period has data
◆ all_entries recued-core.billable-hours.entry.search
Search entry on billable hours
skip: step.by_period equal true
◆ period_entries recued-core.billable-hours.entry.search
Search entry on billable hours
skip: step.by_period equal false
◆ rollup_all recued-core.billable-hours.entry.unbilled_rollup
Unbilled rollup entry on billable hours
skip: step.by_period equal true
◆ rollup_period recued-core.billable-hours.entry.unbilled_rollup
Unbilled rollup entry on billable hours
skip: step.by_period equal false
■ rollup coalesce
Use the first available value from: rollup period aggregate, rollup all aggregate, [object Object]
■ rows coalesce
Use the first available value from: period entries records, all entries records,
■ row_count count
Count items in rows
■ billable_rows filter
Filter by condition
■ nonbillable_rows filter
Filter by condition
■ unbilled_rows filter
Filter by condition
■ billed_rows filter
Filter by condition
■ unbilled_lines map
Extract from each item
■ unbilled_keyed map
Extract task from each item
■ unbilled_groups group_by
Group by task_key
■ group_lines map
Extract from each item
■ group_lines_sorted sort
Sort by amount
■ amount_unrounded sum
Sum values in
■ amount_due round
Round amount unrounded to 2 decimal places
■ unbilled_minutes default
Apply default
■ billed_minutes sum
Sum values in
■ nonbillable_minutes sum
Sum values in
■ unbilled_hours_raw math
Calculate: {{step.unbilled_minutes}} / 60
■ unbilled_hours round
Round unbilled hours raw to 2 decimal places
■ nonbillable_hours_raw math
Calculate: {{step.nonbillable_minutes}} / 60
■ nonbillable_hours round
Round nonbillable hours raw to 2 decimal places
■ unbilled_count default
Apply default
■ shown_count count
Count items in unbilled rows
■ complete compare
Check if shown count equals unbilled count
■ partial_warning ternary
Apply ternary
■ table to_table
Format results as a data table
■ card to_summary
Format results as a summary card
▼
Output
summary card
table table
Settings 3 configurable

Configurable at install. Defaults shown — change them anytime in Recued.

limit setting = 200
period setting =
engagement id setting = [object Object]

Uses (3 operations)

Pack operation Get engagement on billable hours recued-core.billable-hours.engagement.get
Pack operation Search entry on billable hours recued-core.billable-hours.entry.search
Pack operation Unbilled rollup entry on billable hours recued-core.billable-hours.entry.unbilled_rollup

Trust & control

What installing this recipe would let it do. Recued grants these permissions at install — review them there before approving.

What it's allowed to do

Read Pack Billable Hours read-only
Read: engagement.get · No approvalRead: entry.search · No approvalRead: entry.unbilled_rollup · No approval

About

Tags

pack:billable-hourstime-trackingboardrecordsv2

Details

40 steps 3 configurable settings recipe_id: list-unbilled-hours