Recued
Menu
← Back to recipes

Bill a period

by recued-core v2 8 views

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.

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.

Bill a period
This recipe

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 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 “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
View pack details, dependencies, and permissions →

Billing

Give a month and your invoice reference. Every billable, not-yet-invoiced entry in that month is stamped with it, and you get the line items and the total to put on the invoice.

⛔⛔ AN HOUR CANNOT BE BILLED TWICE, and that is the one thing this recipe must get right. An entry is selected only if it is billable, not flagged invoiced, and carries no invoice reference — two independent signals, both of which must say never-billed. Either one alone would do under this recipe's own writes, which set both together; the pair is there so that a hand-edited row, a half-applied migration, or a future recipe that sets one and not the other still cannot produce a second charge. Re-running the same month bills nothing further and says so; re-running with a DIFFERENT reference also bills nothing, because selection is on the entry's own state and never on the reference matching.

⚠ The flip side is deliberate: an entry you have hand-annotated with an invoice reference will never be billed by this recipe. It is counted under "already billed" so it is visible rather than silently missing.

This does not create, send, or reconcile an invoice. It stamps your time records and hands you the lines. Putting them on an invoice — and getting paid — is the seller packs' job, or your accountant's. Nothing here talks to a payment provider.

Non-billable entries are never stamped and never appear in the lines. They stay unbilled forever by design.

⛔⛔ THE INVOICE FOOTS: money is rounded PER TASK GROUP, and the total is the SUM OF THE ROUNDED GROUP AMOUNTS. This is deliberately not the same as rounding once at the end — the two can differ by a penny or two, and when they do, the footing one is correct. A client checking your invoice with a calculator adds up the printed lines; a total that disagrees with them is a defect they will find and you will have to explain. ⚠ The consequence: list-unbilled-hours groups the same way for the same reason, so the preview and the bill agree.

Hours are still derived from whole MINUTES, once per group. Minutes are what is stored; money is computed from them at the group level and never per entry, so no single line's rounding can drift.

Entries with no task reference group together into ONE blank-labelled line — whether the field was left empty or was never set at all. Those are different values in storage and would otherwise become two lines, the second one labelled null on an invoice you send a client. That is a real line on your invoice, not an error — it is the work you did not tag.

Stamping is per entry and not transactional across the set. If the run dies part-way, some entries carry the reference and some do not; re-running stamps the remainder under the same reference rather than starting again, which is why the reference is yours to supply rather than generated.

How it works 41 steps

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

Process (41 steps)
engagement_id trim
Trim whitespace from setting engagement id
period trim
Trim whitespace from setting period
invoice_ref trim
Trim whitespace from setting invoice ref
inputs_valid all
Check if all conditions are true
inputs_guard guard
Stop if inputs valid equals
engagement ?
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_entries ?
rows default
Apply default
row_count count
Count items in rows
billable_rows filter
Filter by condition
to_bill filter
Filter by condition
billable_count count
Count items in billable rows
to_bill_count count
Count items in to bill
already_billed_count math
Calculate billable count minus to bill count
nothing_to_bill compare
Check if to bill count equals 0
billed_minutes sum
Sum values in
billed_hours_raw math
Calculate: {{step.billed_minutes}} / 60
billed_hours round
Round billed hours raw to 2 decimal places
line_items map
Extract from each item
line_items_keyed map
Extract task from each item
groups group_by
Group by task_key
group_lines map
Extract from each item
group_lines_sorted sort
Sort by amount
total_unrounded sum
Sum values in
total round
Round total unrounded to 2 decimal places
group_count count
Count items in groups
invoiced_at date_add
Add 0 seconds to
stamp ?
stamp_results map
Extract from each item
stamped_ok filter
Filter by condition
stamp_failed filter
Filter by condition
stamped_count count
Count items in stamped ok
failed_count count
Count items in stamp failed
all_stamped compare
Check if failed count equals 0
partial_warning ternary
Apply ternary
csv to_csv
Serialize rows as a CSV string
lines_table to_table
Format results as a data table
card to_summary
Format results as a summary card
Settings 4 configurable

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

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

About

Tags

pack:billable-hourstime-trackingbillableinvoicingrecordsv2

Details

41 steps 4 configurable settings recipe_id: bill-period