feat(rules): manual-only rules as one-click quick actions on selected transactions
ci / lint-test (push) Successful in 52s
ci / lint-test (push) Successful in 52s
A rule flagged manual_only never runs in the apply-all pass; instead it shows as a button in the transactions bulk bar and applies its actions to the current selection (conditions ignored — the selection is the condition). Recorded as a rule_apply_run, so it reverts from Rules -> Apply History like any other run. Motivation: tagging Home + splitting 50/50 with Sonu was two bulk actions every time. Now it is one click, and any other combo can be defined the same way. Extracts the action-application and snapshot logic from the apply route into src/lib/rule-actions.ts so both callers share one implementation — splits upsert rather than delete+reinsert, so settled flags survive.
This commit is contained in:
@@ -166,6 +166,7 @@ export function useBulkAction() {
|
||||
merchant_normalized?: string;
|
||||
splits?: { participant_id: number; share_percent: number }[];
|
||||
tag_id?: number;
|
||||
rule_id?: number;
|
||||
}) => {
|
||||
const res = await fetch("/api/transactions/bulk", {
|
||||
method: "POST",
|
||||
@@ -188,6 +189,16 @@ export function useBulkAction() {
|
||||
if (variables.action === "tag" || variables.action === "untag") {
|
||||
qc.invalidateQueries({ queryKey: ["tags"] });
|
||||
}
|
||||
// A quick action can touch category, tags and splits at once, and records
|
||||
// a revertible run — refresh everything it could have changed.
|
||||
if (variables.action === "apply_rule") {
|
||||
qc.invalidateQueries({ queryKey: ["tags"] });
|
||||
qc.invalidateQueries({ queryKey: ["splits"] });
|
||||
qc.invalidateQueries({ queryKey: ["shared-transactions"] });
|
||||
qc.invalidateQueries({ queryKey: ["participant-balances"] });
|
||||
qc.invalidateQueries({ queryKey: ["analytics"] });
|
||||
qc.invalidateQueries({ queryKey: ["rule-runs"] });
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
@@ -459,6 +470,8 @@ export interface RuleRow {
|
||||
conditions: { field: string; operator: string; value: string }[];
|
||||
actions: { set_category?: string; add_tag_ids?: number[]; set_merchant?: string; apply_split?: { participant_id: number; share_percent: number }[] };
|
||||
enabled: boolean;
|
||||
/** Excluded from the apply-all run; fired by hand as a quick action instead. */
|
||||
manual_only?: boolean;
|
||||
priority: number;
|
||||
created_at: string;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user