Skip to content

Add category tax defaults to Expense defaults to reach parity with Classic #99410

Description

@JmillsExpensify

Background

R1 (#92739) centralized workspace merchant rules into the Expense defaults tab, and R2 (#92741) added the 12 locked Merchant types defaults. Every rule in that tab matches on a merchant or a merchant type.

Classic lets an admin set a default tax rate on a category, and we have no equivalent on the new platform. Any workspace using that setting today loses it when they move over, which makes this a backward-compatibility gap and a blocker on removing the beta.

This issue adds Category as a second condition for Apply expense defaults, so an admin can set a default tax rate for a category. Expense defaults has not yet been migrated to the new rules system, so the rule carries real constraints: one condition per rule, tax as the only available default, and no retroactive application. We express all three with the lock affordance R1 and R2 already established.

Scope

  • Add Category as a second condition to the Apply expense defaults branch of New rule, alongside the existing Merchant condition.
  • Allow exactly one condition per rule. Setting one locks the other, because Expense defaults has not been migrated to the new rules system.
  • When the condition is Category, allow only Tax in the defaults to apply and lock every other field.
  • Lock Apply to existing unsubmitted expenses for category rules, since a category tax default only applies to expenses created after the rule is saved.
  • Show category rules in a new Categories subsection of the Expense defaults table.
  • No change to the New rule option list or its copy. This extends the existing Apply expense defaults branch; it does not add a fifth rule type.

Product and design details

Image Image

Applicability

The Category condition is available to workspace admins when taxes are enabled on the workspace. Taxes are what the rule sets, so with taxes off there is nothing to configure. In that case the Category condition row renders locked, and the Merchant condition continues to work as it does today.

Condition: one of Merchant or Category

The If any expense matches: section has two rows, Merchant and Category, in that order. Each shows its selected value beneath its label, and nothing beneath it when unset.

Setting a value in one row locks the other:

  • The locked row replaces its chevron with the lock icon and no longer opens a picker.
  • Selecting the locked row opens the existing centered-modal explainer. Reuse the R1 modal pattern; no new component.
  • The explainer is informational only, with a single Got it action. It changes no selections.

Explainer copy, which differs by direction:

  • Category locked, because a merchant is set. Heading: Only one condition per rule. Body: This rule already matches on a merchant. Reset the rule to match on a category instead.
  • Merchant locked, because a category is set. Heading: Only one condition per rule. Body: This rule already matches on a category. Reset the rule to match on a merchant instead.
  • Category locked, because taxes are disabled. Heading: Turn on taxes first. Body: Category rules set a default tax rate. Turn on taxes in your workspace settings to use them.

Reset appears in the RHP header once either condition is set. It clears both conditions and every default, and unlocks every row. It does not appear on a rule with nothing selected.

Defaults to apply

The Then apply the following defaults: section lists the sum of all conditions that apply to Merchant and Category. Which rows are available depends on the condition:

  • Condition is Merchant: every row is enabled. This is today's behavior and it does not change.
  • Condition is Category: only Tax is enabled. Every other row shows the lock icon and opens the explainer when selected.
  • No condition set yet: every row is enabled, and rows lock as soon as a category is chosen.

Explainer copy for a row locked by the category condition. Heading: Only tax is available for category rules. Body: Category rules can set a default tax rate. To set other defaults, match on a merchant instead.

An admin can select multiple categories to set tax defaults in bulk. The category picker excludes any category that already has one.

Apply to existing unsubmitted expenses and Preview matches

For merchant rules, both controls behave exactly as they do today.

For category rules:

  • The toggle is locked in the off position and shows the lock icon in place of the switch. Selecting it opens the explainer. Heading: Category rules apply going forward. Body: A default tax rate applies to new expenses in this category. Expenses that already exist won't change.
  • Preview matches is hidden, not locked, since there is no set of existing expenses to preview.

Table row and the Categories subsection

Category rules render in a new Categories subsection of the Expense defaults table, positioned after Merchant types. The full subsection order is Categories, MerchantsMerchant types.

  • Type: the Update pill, consistent with every other row in this tab.
  • ConditionCategory is "Meals and Entertainment".
  • RuleUpdate tax to "GST (10%)", using the tax rate's name as it appears in workspace tax settings.
  • Clicking a row opens the same Apply expense defaults RHP it was created in, with the condition and tax rate pre-filled.

Category rules are admin-created, so unlike Merchant types rows they are editable and deletable.

Subsection-header logic, consistent with R1 and R2: when the only rules in the tab are the locked Merchant types defaults, show a flat list with no headers. Headers appear once at least one admin-created rule exists. A header renders only when its own subsection has at least one row, so a workspace with a category rule and no custom merchant rules sees Merchant types and Categories and no Merchants header.

Truncation: the Rule column truncates with  and shows the full rule text in a tooltip on hover, consistent with existing behavior. A category rule is a single clause, so truncation will be rare here; no change to the tooltip itself though, if it applies.

Empty state: unchanged. The Merchant types defaults always exist, so the tab is never empty and this issue adds no empty state.

Existing Classic-configured defaults

A workspace that already set a category default tax rate in Classic sees a matching row in Categories when this ships. Those rules are the same objects, not copies. Editing the tax rate from this RHP updates the rule Classic reads, and deleting the row removes it in both places.

Mobile

The RHP renders as a full-screen page with the same rows, the same order, and the same locks. The explainer uses the existing modal pattern. No mobile-specific layout.

Category details RHP

No changes to the Category rules section in the category details RHP (#92742). Category tax defaults surface there through that release's existing pattern.

QA Examples

  • An admin opens New rule > Apply expense defaults and sets Category to Meals and Entertainment: the Merchant condition row locks, and in the defaults section every row except Tax locks.
  • They set Tax to GST (10%) and save: a row appears in Categories with the Update pill, Category is "Meals and Entertainment", and Update tax to "GST (10%)".
  • A different admin sets Merchant to Starbucks first: the Category row locks and every row in the defaults section stays enabled, exactly as today.
  • In that state they select the locked Category row: the explainer opens reading This rule already matches on a merchant. Reset the rule to match on a category instead. Nothing changes. They select Reset, both conditions clear, and every row unlocks.
  • An admin with a saved category rule selects the locked Apply to existing unsubmitted expenses toggle: the explainer opens and the toggle stays off. An unsubmitted Meals and Entertainment expense created yesterday keeps no tax; the next expense created in that category gets GST (10%).
  • A workspace that set a default tax rate on Meals and Entertainment in Classic opens Expense defaults after this ships: the rule is already in Categories. Changing its tax rate to VAT (20%) and saving updates the rule Classic reads.
  • An admin tries to create a second rule for Meals and Entertainment: the category picker doesn't offer that category.
  • A workspace with only the 12 locked Merchant types rows adds one category rule: the Merchant types and Categories headers appear, and no Merchants header renders.
  • A workspace with taxes turned off opens the flow: the Category condition row is locked and reads Turn on taxes in your workspace settings to use them. The Merchant condition still works normally.
Issue OwnerCurrent Issue Owner: @Krishna2323

Metadata

Metadata

Labels

ImprovementItem broken or needs improvement.InternalRequires API changes or must be handled by Expensify staffReviewingHas a PR in reviewWeeklyKSv2

Type

No type

Projects

Status
No status

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions