Recued
Menu
← Back to recipes

Tag a month of lines

by recued-core v3 11 views

Use “Tag a month of lines” in Recued. One tree at a time: every line in a period on one page, with a picker in the tag cell.

Complete workflow

Ledger book 16 pinned recipes

Use Ledger book in Recued for accounting, double entry, budget, and records. It includes 44 built-in actions and 15 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.

Tag a month of lines
This recipe

Use “Tag a month of lines” in Recued. One tree at a time: every line in a period on one page, with a picker in the tag cell.

pack:ledger-bookaccountingtagsrecords
by recued-core pinned v3

Use “The accounts” in Recued. Every account with its id — what you post to, and what anything else in this workflow needs before it can name one.

pack:ledger-bookaccountingaccountsrecords
by recued-core pinned v3

Use “The tags” in Recued. Every tag with its id and how deep it sits — the trees you can spend against, and the ids the rest of the pack takes.

pack:ledger-bookaccountingtagsrecords
by recued-core pinned v3

Use “What it all comes to” in Recued. Each currency's balance read exactly, then converted at rates you give and added up.

pack:ledger-bookaccountingcurrencyrecords
by recued-core pinned v3

Use “Every budget at once” in Recued. All your budgets for a period, each counting everything under its tag — in four queries, however many budgets you have.

pack:ledger-bookaccountingbudgetrecords
by recued-core pinned v3
Show all 16 recipes

Use “How a budget is doing” in Recued. What a budget has left, counting everything under its tag at any depth.

pack:ledger-bookaccountingbudgetrecords
by recued-core pinned v3

Use “What went under a tag” in Recued. Everything spent under one tag, including every tag beneath it, at any depth.

pack:ledger-bookaccountingtagsbudget
by recued-core pinned v3

Use “The lines under a tag” in Recued. Every transaction line under a tag and everything beneath it — the lines themselves, not a total. With a CSV to copy.

pack:ledger-bookaccountingtagsexport
by recued-core pinned v3

Use “Open an account” in Recued. Adds an account to your chart. Its currency is fixed here and every line posted to it inherits it.

pack:ledger-bookaccountingrecordsv2
by recued-core pinned v2

Use “Post an entry” in Recued. One entry, any number of legs, written in a single all-or-nothing transaction. It will not post unless the legs sum to zero.

pack:ledger-bookaccountingdouble-entryrecords
by recued-core pinned v3

Use “Add a tag” in Recued. Adds a tag anywhere in your tree, at any depth. The tag and its place in the tree are written together or not at all.

pack:ledger-bookaccountingtagsrecords
by recued-core pinned v3

Use “Tag a transaction line” in Recued. Sets which tags a line belongs to, one per tree. Each tag and every tag above it counts the full amount.

pack:ledger-bookaccountingtagsrecords
by recued-core pinned v3

Use “Set a budget” in Recued. A cap on a tag for one period. It counts everything under that tag, at any depth.

pack:ledger-bookaccountingbudgetrecords
by recued-core pinned v3

Use “Move a tag” in Recued. Puts a tag inside a different one. Everything recorded under it follows automatically — no transaction is rewritten.

pack:ledger-bookaccountingtagsrecords
by recued-core pinned v3

Use “Delete a tag” in Recued. Removes a tag and everything beneath it. Refuses while anything is still tagged with it.

pack:ledger-bookaccountingtagsrecords
by recued-core pinned v3
View pack details, dependencies, and permissions →

One tree, many lines

Post the month from the statement, then categorise it here: pick a tree, get every line in the period on one page, and tab down the tag column. The picker only offers tags from the tree you chose — so the one-per-tree rule is in the control, not in a refusal after you have typed.

One tree per run, and that is the shape rather than a limitation. A page with a column per tree would need columns that vary with your data, and columns are authored while trees are records — add a fourth tree and no recipe could grow a fourth column. So the multiplicity lives in runs: three trees is three passes, each one a page you tab down.

What you can and cannot type

Only the tag cell accepts typing. The line, its amount and its date are shown so you know what you are categorising, and locked so you cannot re-point a tag at a different transaction by editing the row it is sitting in. Shown and editable are different questions, and only the second is a write.

Leave a cell blank to skip that line. Blank means "not now", never "remove its tag" — clearing a dimension is naming a different tag in it, which is what tag-leg is for.

What it writes

One leg_tag row per line you tagged, carrying the line's FULL amount — the same money counted at every level above the tag you picked. Existing tags from OTHER trees are untouched; a tag already set in THIS tree is replaced.

All of it lands or none of it does. A half-applied page would leave some lines categorised and no way to tell which, on a screen you have already moved on from.

Limits

50 lines a page, and the ceiling is arithmetic rather than a preference. Re-tagging a line is two writes — the old tag out, the new one in — and a batch holds 100. A 100-line page could therefore be filled in and then refused, which is the one failure worth designing away: you would have done the work already.

Past 50 it refuses BEFORE drawing the page, so you are never shown a grid you cannot submit. Narrow it by account — and only by account: a period is a whole month here, so there is no shorter one to ask for.

It needs FULL access at install

This recipe is DENIED if the pack was installed with write access — pick all. It drives a batch operation whose allow-list contains a delete (leg_tag.apply — replacing a tag means deleting the old row), and a batch's risk floor is the union of everything it may do, so the whole operation is classed destructive. write does not grant that.

The refusal is operation_not_granted at the gateway, which reads like a bug in the recipe rather than a scope you chose at install. It is not something the recipe can detect and explain for you — the denial happens before its first step runs.

How it works 95 steps

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

Process (95 steps)
tree trim
Trim whitespace from setting tree
period trim
Trim whitespace from setting period
inputs_ok all
Check if all conditions are true
inputs_guard guard
Stop if inputs ok equals
tree_tag ?
tree_found compare
Check if tree tag record id has data
tree_found_guard guard
Stop if tree found equals
is_a_root compare
Check if tree tag record root ref equals tag/{{step.tree}}
root_guard guard
Stop if is a root equals
root_ref template
Generate text from a template
account_id trim
Trim whitespace from setting account id
has_account compare
Check if account id has data
submitted default
Apply default
submitted_count count
Count items in submitted
has_submission compare
Check if submitted count is greater than 0
lines_any ?
skip: step.has_account equal true
lines_one ?
skip: step.has_account equal false
lines coalesce
Use the first available value from: lines one, lines any
line_rows default
Apply default
line_count count
Count items in line rows
page_count_fits compare
Check if line count is at most 50
line_page_complete compare
Check if lines next cursor is empty
page_fits all
Check if all conditions are true
page_guard guard
Stop if page fits equals
line_refs map
Extract from each item
page_leg_refs pluck
Extract leg_ref from each item
has_lines compare
Check if line count is greater than 0
current ?
skip: step.has_lines equal false
current_rows default
Apply default
current_count count
Count items in current rows
current_count_fits compare
Check if current count is at most 50
current_cursor_empty compare
Check if current next cursor is empty
current_page_complete all
Check if all conditions are true
current_page_guard guard
Stop if current page complete equals
with_current enrich_by
Apply enrich_by
with_current_name map
Extract current_tag_ref from each item
grid_rows map
Extract from each item
picked filter
Filter by condition
picked_count count
Count items in picked
nothing_picked all
Check if all conditions are true
empty_guard guard
Stop if nothing picked equals
picked_leg_refs pluck
Extract leg_ref from each item
distinct_picked_leg_refs unique
Remove duplicates from
distinct_picked_count count
Count items in distinct picked leg refs
one_assignment_per_line compare
Check if distinct picked count equals picked count
duplicate_line_guard guard
Stop if one assignment per line equals
on_page filter
Filter by condition
on_page_count count
Count items in on page
all_lines_on_page compare
Check if on page count equals picked count
line_scope_guard guard
Stop if all lines on page equals
canonical_tags map
Extract tag_ref from each item
canonical_tag_rows filter
Filter by condition
canonical_tag_count count
Count items in canonical tag rows
all_tag_refs_canonical compare
Check if canonical tag count equals picked count
tag_ref_guard guard
Stop if all tag refs canonical equals
tag_id_rows map
Extract tag_ref from each item
selected_tags ?
selected_rows map
Extract from each item
selected_found filter
Filter by condition
selected_found_count count
Count items in selected found
all_tags_found compare
Check if selected found count equals picked count
tag_found_guard guard
Stop if all tags found equals
selected_in_tree filter
Filter by condition
selected_in_tree_count count
Count items in selected in tree
all_tags_in_tree compare
Check if selected in tree count equals picked count
tag_scope_guard guard
Stop if all tags in tree equals
selected_with_leg_id map
Extract leg_ref from each item
selected_with_desired_id map
Extract from each item
desired_ids pluck
Extract desired_id from each item
existing ?
skip: step.has_submission equal false
existing_rows default
Apply default
existing_count count
Count items in existing rows
existing_count_fits compare
Check if existing count is at most picked count
existing_cursor_empty compare
Check if existing next cursor is empty
existing_page_complete all
Check if all conditions are true
existing_page_guard guard
Stop if existing page complete equals
existing_ids pluck
Extract id from each item
superseded filter
Filter by condition
remove_ops map
Extract from each item
with_line enrich_by
Apply enrich_by
with_existing enrich_by
Apply enrich_by
new_tags filter
Filter by condition
changed_tags filter
Filter by condition
tag_ops map
Extract from each item
count_ops map
Extract from each item
ops flatten
Flatten nested lists in
op_count count
Count items in ops
fits compare
Check if op count is at most 100
size_guard guard
Stop if fits equals
has_ops compare
Check if op count is greater than 0
should_post all
Check if all conditions are true
post ?
skip: step.should_post equal false
replaced count
Count items in remove ops
changed_count count
Count items in changed tags
card to_summary
Format results as a summary card
Settings 5 configurable

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

tree setting = [object Object]
limit setting = 50
period setting = [object Object]
account id setting =
assignments setting =

About

Tags

pack:ledger-bookaccountingtagsrecordsv3

Details

95 steps 5 configurable settings recipe_id: tag-lines