Skip to content

[hold] remove rulesRevamp beta. - #98662

Open
Krishna2323 wants to merge 17 commits into
Expensify:mainfrom
Krishna2323:krishna2323/remove-rules-revamp-beta
Open

[hold] remove rulesRevamp beta.#98662
Krishna2323 wants to merge 17 commits into
Expensify:mainfrom
Krishna2323:krishna2323/remove-rules-revamp-beta

Conversation

@Krishna2323

@Krishna2323 Krishna2323 commented Aug 14, 2026

Copy link
Copy Markdown
Contributor

Explanation of Change

Fixed Issues

$ #97686
$ #98699
PROPOSAL:

Tests

1. Rules

  1. On a non-beta account, open Workspace → Rules.
  2. Verify the revamped tabbed page appears: General, Card restrictions, Expense defaults, Require fields, Flag for review.
  3. Open each tab and add/edit a rule. Verify there are no blank or Not Found pages.

2. Workflows

  1. Open Workspace → Workflows.
  2. Verify the revamped tabs: Submissions, Approvals, Payments, Advanced.
  3. As a read-only member, verify Workflows still shows the read-only state.

3. Smart Limit deep link

  1. Disable Approvals in Workflows settings > go to Expensify Card → Issue new card → Limit type and click the disabled-description link.
  2. Verify it opens Workflows on the Approvals tab.
  3. Repeat from an existing card's Limit type.

4. Categories

  1. Go to Categories → ⋮ and verify the old Settings option is gone.
  2. Open a category and verify only the revamped rule rows are shown. No legacy rows like Flag amounts over, Require receipts over, or Required fields.

5. Tags

  1. Go to Tags → ⋮ → Settings and verify Require tags and Track billable are gone.
  2. For independent multi-level tags, verify there's no Required column or detail-page Required toggle.
  3. Go to Rules → Require fields and verify per-level Required rows work.

6. Final regression sweep

  1. On a non-beta account, check Workspace overview → More features → Categories → Tags → Workflows → Rules → Expensify Card and the Rules sub-pages.
  2. Verify there are no pre-revamp screens or Not Found pages.
  • Verify that no errors appear in the JS console

Offline tests

  • Same as tests

QA Steps

  • Same as tests

  • Verify that no errors appear in the JS console

PR Author Checklist

  • I linked the correct issue in the ### Fixed Issues section above
  • I wrote clear testing steps that cover the changes made in this PR
    • I added steps for local testing in the Tests section
    • I added steps for the expected offline behavior in the Offline steps section
    • I added steps for Staging and/or Production testing in the QA steps section
    • I added steps to cover failure scenarios (i.e. verify an input displays the correct error message if the entered data is not correct)
    • I turned off my network connection and tested it while offline to ensure it matches the expected behavior (i.e. verify the default avatar icon is displayed if app is offline)
    • I tested this PR with a High Traffic account against the staging or production API to ensure there are no regressions (e.g. long loading states that impact usability).
  • I included screenshots or videos for tests on all platforms
  • I ran the tests on all platforms & verified they passed on:
    • Android: Native
    • Android: mWeb Chrome
    • iOS: Native
    • iOS: mWeb Safari
    • MacOS: Chrome / Safari
    • MacOS: Desktop
  • I verified there are no console errors (if there's a console error not related to the PR, report it or open an issue for it to be fixed)
  • I verified there are no new alerts related to the canBeMissing param for useOnyx
  • I followed proper code patterns (see Reviewing the code)
    • I verified that any callback methods that were added or modified are named for what the method does and never what callback they handle (i.e. toggleReport and not onIconClick)
    • I verified that comments were added to code that is not self explanatory
    • I verified that any new or modified comments were clear, correct English, and explained "why" the code was doing something instead of only explaining "what" the code was doing.
    • I verified any copy / text shown in the product is localized by adding it to src/languages/* files and using the translation method
      • If any non-english text was added/modified, I used JaimeGPT to get English > Spanish translation. I then posted it in #expensify-open-source and it was approved by an internal Expensify engineer. Link to Slack message:
    • I verified all numbers, amounts, dates and phone numbers shown in the product are using the localization methods
    • I verified any copy / text that was added to the app is grammatically correct in English. It adheres to proper capitalization guidelines (note: only the first word of header/labels should be capitalized), and is either coming verbatim from figma or has been approved by marketing (in order to get marketing approval, ask the Bug Zero team member to add the Waiting for copy label to the issue)
    • I verified proper file naming conventions were followed for any new files or renamed files. All non-platform specific files are named after what they export and are not named "index.js". All platform-specific files are named for the platform the code supports as outlined in the README.
    • I verified the JSDocs style guidelines (in STYLE.md) were followed
  • If a new code pattern is added I verified it was agreed to be used by multiple Expensify engineers
  • I followed the guidelines as stated in the Review Guidelines
  • I tested other components that can be impacted by my changes (i.e. if the PR modifies a shared library or component like Avatar, I verified the components using Avatar are working as expected)
  • I verified all code is DRY (the PR doesn't include any logic written more than once, with the exception of tests)
  • I verified any variables that can be defined as constants (ie. in CONST.ts or at the top of the file that uses the constant) are defined as such
  • I verified that if a function's arguments changed that all usages have also been updated correctly
  • If any new file was added I verified that:
    • The file has a description of what it does and/or why is needed at the top of the file if the code is not self explanatory
  • If a new CSS style is added I verified that:
    • A similar style doesn't already exist
    • The style can't be created with an existing StyleUtils function (i.e. StyleUtils.getBackgroundAndBorderStyle(theme.componentBG))
  • If new assets were added or existing ones were modified, I verified that:
    • The assets are optimized and compressed (for SVG files, run npm run compress-svg)
    • The assets load correctly across all supported platforms.
  • If the PR modifies code that runs when editing or sending messages, I tested and verified there is no unexpected behavior for all supported markdown - URLs, single line code, code blocks, quotes, headings, bold, strikethrough, and italic.
  • If the PR modifies a generic component, I tested and verified that those changes do not break usages of that component in the rest of the App (i.e. if a shared library or component like Avatar is modified, I verified that Avatar is working as expected in all cases)
  • If the PR modifies a component related to any of the existing Storybook stories, I tested and verified all stories for that component are still working as expected.
  • If the PR modifies a component or page that can be accessed by a direct deeplink, I verified that the code functions as expected when the deeplink is used - from a logged in and logged out account.
  • If the PR modifies the UI (e.g. new buttons, new UI components, changing the padding/spacing/sizing, moving components, etc) or modifies the form input styles:
    • I verified that all the inputs inside a form are aligned with each other.
    • I added Design label and/or tagged @Expensify/design so the design team can review the changes.
  • If a new page is added, I verified it's using the ScrollView component to make it scrollable when more elements are added to the page.
  • I added unit tests for any new feature or bug fix in this PR to help automatically prevent regressions in this user flow.
  • If the main branch was merged into this PR after a review, I tested again and verified the outcome was still expected according to the Test steps.

Screenshots/Videos

Android: Native
Android: mWeb Chrome
iOS: Native
iOS: mWeb Safari
MacOS: Chrome / Safari
Monosnap.screencast.2026-08-21.12-57-45.mp4

Signed-off-by: krishna2323 <belivethatkg@gmail.com>
@Krishna2323
Krishna2323 marked this pull request as ready for review August 14, 2026 17:08
@Krishna2323
Krishna2323 requested review from a team as code owners August 14, 2026 17:08
@melvin-bot
melvin-bot Bot requested review from JmillsExpensify and situchan and removed request for a team August 14, 2026 17:09
@melvin-bot

melvin-bot Bot commented Aug 14, 2026

Copy link
Copy Markdown

@situchan Please copy/paste the Reviewer Checklist from here into a new comment on this PR and complete it. If you have the K2 extension, you can simply click: [this button]

@melvin-bot
melvin-bot Bot removed the request for review from a team August 14, 2026 17:09
Comment thread src/pages/workspace/rules/MerchantRules/MerchantRulePageBase.tsx
Comment thread src/pages/workspace/rules/SpendRules/SpendRulePageBase.tsx

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 0489bafb3c

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Signed-off-by: krishna2323 <belivethatkg@gmail.com>
…t tests

Signed-off-by: krishna2323 <belivethatkg@gmail.com>
@codecov

codecov Bot commented Aug 16, 2026

Copy link
Copy Markdown

Codecov Report

❌ Looks like you've decreased code coverage for some files. Please write tests to increase, or at least maintain, the existing level of code coverage. See our documentation here for how to interpret this table.

Files with missing lines Coverage Δ
src/CONST/index.ts 94.85% <ø> (ø)
...ables/WorkspaceTagsTable/WorkspaceTagsTableRow.tsx 90.32% <100.00%> (-0.31%) ⬇️
src/components/Tables/WorkspaceTagsTable/index.tsx 68.00% <ø> (-1.82%) ⬇️
src/libs/AttendeeUtils.ts 79.31% <ø> (+13.59%) ⬆️
src/libs/CategoryUtils.ts 82.52% <ø> (+7.30%) ⬆️
src/libs/PolicyUtils.ts 78.70% <100.00%> (+0.16%) ⬆️
src/libs/actions/Policy/Policy.ts 70.45% <ø> (-0.35%) ⬇️
src/libs/actions/Policy/Tag.ts 68.19% <ø> (+4.29%) ⬆️
...tings/Wallet/WalletExpensifyCardSpendRulesPage.tsx 0.00% <ø> (ø)
src/pages/workspace/AccessOrNotFoundWrapper.tsx 94.44% <100.00%> (-0.16%) ⬇️
... and 46 more
... and 228 files with indirect coverage changes

@JmillsExpensify JmillsExpensify left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM though no product review required.

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Hooray!

Reviewed commit: 3b1bbfd304

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

@MelvinBot

Copy link
Copy Markdown
Contributor

Review — remove rulesRevamp beta

LGTM overall. This is a clean, mechanical beta removal that keeps the "beta on" path everywhere. Verified static consistency + a web smoke test; one non-blocking cleanup worth deciding on before merge.

What I verified ✅

  • No leftovers: zero remaining references to RULES_REVAMP / rulesRevamp / isRulesRevampEnabled / isRevamp anywhere in src or tests.
  • No orphaned imports/helpers: every removed symbol (formatRequiredFieldsTitle, formatRequireReceiptsOverText, isAttendeeTrackingEnabled, navigateToCategoriesSettings, setPolicyRequiresTag, setPolicyProhibitedExpense, the titleKey props, etc.) has 0 remaining usages in its file. TranslationPaths (SpendRulePageBase.tsx:61) and IconAsset (MerchantRulePageBase.tsx:74) are still used, so they're correctly left in.
  • getControlOnlySelectedParts test change is sound: flipping 'rules''perDiem' in CopyPolicySettingsUtilsTest.ts is backed by source — the util derives control-only parts from canPolicyAccessFeature, which now returns true for Collect + Rules, so rules is genuinely no longer Control-only.
  • Typecheck: tsc --noEmit reports no errors in the changed areas.
  • Web smoke test: the revamped Rules page (General / Card restrictions / Expense defaults / Field requirements / Flag for review / Agents) and the Workflows page both render by default. On a Collect-plan workspace the gated tabs correctly show the Upgrade panel instead of crashing. No visible crashes or error boundaries.

Non-blocking: dead legacy pages left behind 🧹

WorkspaceSplitNavigator now points RULESPolicyRulesPageRevamp and WORKFLOWSWorkspaceWorkflowsPageRevamp directly (WorkspaceSplitNavigator.tsx), and the legacy pages no longer render their revamp counterparts. That leaves PolicyRulesPage.tsx and WorkspaceWorkflowsPage.tsx unreachable in production — they're now only referenced by tests:

  • tests/ui/AgentsPromoBannersTest.tsxPolicyRulesPage
  • tests/ui/WorkspaceWorkflowsPayerRowTest.tsx and tests/ui/WorkspaceWorkflowsLoadMoreTest.tsxWorkspaceWorkflowsPage

So those suites now validate components users can't reach, which will drift and give false confidence. Consider deleting the legacy pages and repointing (or removing) those tests as part of this PR, or confirm it's intentionally deferred to a follow-up. (Renaming the …Revamp files/props now that there's no non-revamp variant is cosmetic and fine to leave for later.)

Screenshots

Revamped Rules page and Workflows page rendering by default (no beta):

Revamped Rules page (General tab) rendering by default after beta removal

Revamped Rules page (General tab) rendering by default after beta removal

Workflows page rendering after beta removal

Workflows page rendering after beta removal

🤖 Generated by MelvinBot · web smoke test on dev NewDot · console-log inspection isn't available via the web agent-device, so "no console errors" reflects the absence of any crash/error-boundary, not a raw console read.

@MelvinBot

Copy link
Copy Markdown
Contributor

Regression hunt — remove rulesRevamp beta

No regressions found. This is a faithful beta removal: every isRulesRevampEnabled ? A : B collapses to the beta‑ON branch A, every &&/|| guard simplifies to its equivalent, and the deleted !isRulesRevampEnabled blocks had revamp replacements that stay reachable. Static audit + typecheck + a web smoke test are all clean. One intended behavior shift to QA (below), not a code defect.

What I checked ✅

  • All boolean simplifications are logically equivalent to substituting isRulesRevampEnabled = true — verified hunk by hunk, including the trickier ones (RulesBillableDefaultPage !isRevamp || (…)(…), WorkspaceTagsPage !(isRevamp && isMultiLevelTags)!isMultiLevelTags, CategorySettingsPage's two categoryRulesEnabled blocks).
  • shouldBeBlocked prop changes are safe. The pages that dropped the prop entirely (FlagForReviewRulePageBase, RequireFieldsRulePageBase, MerchantTypeRulePageBase, RulesNewPage, RulesRequireFieldsPage, RulesRequireReceiptsPage, PolicyRulesPageRevamp) each had only shouldBeBlocked={!isRulesRevampEnabled} before → false under beta‑on → undefined now (both falsy). The ones that kept !canWriteRules correctly preserved that guard. No access guard was accidentally dropped.
  • No orphaned or undefined symbols. Every removed import/local (titleKey, getItemIcon, legacyFormContent, formatRequiredFieldsTitle, formatRequireReceiptsOverText, setPolicyRequiresTag, toggleBillableExpenses, setPolicyProhibitedExpense, etc.) has zero remaining references; every retained import (TranslationPaths, IconAsset, Switch, isBetaEnabled for other betas) is still used. tsc --noEmit reports no errors in the changed areas.
  • No stale callers. arePolicyRulesEnabled / canPolicyAccessFeature / isPolicyFeatureEnabled dropped their isRulesRevampEnabled param; no caller in src or tests still passes it (would be a TS error).
  • Export/navigator rewire is correct. WorkspaceWorkflowsPageRevamp reads policy from props, so wrapping its export in withPolicy is required, and the navigator renders it directly (no double‑wrap). PolicyRulesPageRevamp reads policy via usePolicy, so it correctly stays unwrapped.
  • Moved functionality stays reachable. The requiresTag / trackBillable toggles deleted from WorkspaceTagsSettingsPage live in the revamp on RulesRequireFieldsPage / RulesBillableDefaultPage, gated on ARE_RULES_ENABLED with accessVariants=[ADMIN, PAID] — which Collect admins now satisfy. Same for the category "Settings" secondary action (now reached by tapping a category row).
  • Web smoke test: the revamped Rules and Workflows pages render by default; Collect‑plan gated tabs show the Upgrade panel rather than crashing.

The one behavior shift to QA (intended, not a bug) ⚠️

Six untouched call sites already called arePolicyRulesEnabled(policy, policyCategories) with no beta arg, so they used to compute false for Collect and now compute the real value: ViolationsUtils.ts:772, ModifiedExpenseMessage.ts:545, SplitExpenseEditPage.tsx:151, MoneyRequestConfirmationList.tsx:378, useGettingStartedItems.ts:282, DynamicWorkspaceExpensifyCardDetailsPage.tsx:163. This is exactly the PR's intent (Collect graduates to Rules), but it means existing Collect workspaces that already have areRulesEnabled/category rules in Onyx will now surface rule violations and category description requirements. Worth a QA pass to confirm the backend treats Collect rules the same way the client now does — the client change is correct regardless, but this is where a product/backend mismatch would show up first.

Note

I could not execute the jest suite in this environment, so the above rests on static analysis + typecheck + the web smoke test rather than a local test run — CI's Jest job still covers the four updated test files.

🤖 Generated by MelvinBot · analysis + adversarial static audit at 3b1bbfd.

Signed-off-by: krishna2323 <belivethatkg@gmail.com>
@JS00001
JS00001 self-requested a review August 18, 2026 15:19
Signed-off-by: krishna2323 <belivethatkg@gmail.com>
@Krishna2323

Copy link
Copy Markdown
Contributor Author

@MelvinBot review

Signed-off-by: krishna2323 <belivethatkg@gmail.com>
Signed-off-by: krishna2323 <belivethatkg@gmail.com>
@MelvinBot

Copy link
Copy Markdown
Contributor

Review — remove rulesRevamp beta (re-review at 506fcdf)

🔴 Blocking: this PR currently fails typecheck. The merge from main / conflict-resolution commit (506fcdf) pulled in three files that still reference CONST.BETAS.RULES_REVAMP, but this PR deleted that beta from the enum. npm run typecheck fails with three TS2339: Property 'RULES_REVAMP' does not exist errors:

These are the dynamic-navigation siblings of pages this PR already collapsed (CategorySettingsPage, WorkspaceTagsPage), and they're reachable in the new workspace nav — so beyond the compile break, even if they compiled they'd fall back to isRulesRevampEnabled === false at runtime (isBetaEnabled(undefined)false) and render the pre-revamp rows the PR is meant to remove (e.g. the tag detail "Required" toggle, the category "Requires category" toggle). This directly contradicts test steps 11–13.

Fix: collapse the beta in these three files to the beta-ON path, exactly as done for their non-dynamic counterparts — remove isRulesRevampEnabled, delete the !isRulesRevampEnabled legacy blocks, and simplify WorkspaceTagsTable's shouldShowRequiredColumn (its !isBetaEnabled(RULES_REVAMP) term becomes false, so the Required column drops out).

tsc output
src/components/Tables/WorkspaceTagsTable/index.tsx(82,106): error TS2339: Property 'RULES_REVAMP' does not exist on type '{ readonly ALL: "all"; ... }'.
src/pages/workspace/categories/DynamicWorkspaceCategoriesSettingsPage.tsx(48,60): error TS2339: Property 'RULES_REVAMP' does not exist on type '{ readonly ALL: "all"; ... }'.
src/pages/workspace/tags/DynamicWorkspaceViewTagsPage.tsx(81,60): error TS2339: Property 'RULES_REVAMP' does not exist on type '{ readonly ALL: "all"; ... }'.

What's good ✅

  • The new approval-tab deep-link fix (e87f940) is correct: DynamicExpensifyCardLimitTypePage and LimitTypeStep now pass CONST.TAB.WORKFLOWS.APPROVALS into WORKSPACE_WORKFLOWS.getRoute, and the revamp page reads route.params?.tab (WorkspaceWorkflowsPageRevamp.tsx:111), so the link lands on the Approvals tab.
  • The beta collapse across the originally-changed files remains clean — no leftover RULES_REVAMP refs within the PR's own diff.

Still worth addressing (from the earlier review, unchanged)

  • The legacy PolicyRulesPage.tsx and WorkspaceWorkflowsPage.tsx are now unreachable in production (navigator points straight at the …Revamp pages) but are still exercised only by tests/ui/AgentsPromoBannersTest.tsx, WorkspaceWorkflowsPayerRowTest.tsx, and WorkspaceWorkflowsLoadMoreTest.tsx. Consider deleting them + repointing those tests here, or confirm it's a deliberate follow-up.

Testing note

I attempted a fresh web smoke test at 506fcdf, but the prestarted browser session was stuck on a blank page (0 accessibility nodes) for the whole drive despite the dev server building cleanly — an infra/session issue, not a product observation, so I couldn't visually confirm the runtime fallback on the two dynamic pages. The typecheck failure above is verified directly via npm run typecheck.


Next Steps: fix the three RULES_REVAMP references, then reply @MelvinBot review to re-check.

🤖 Generated by MelvinBot · re-review at 506fcdf after the merge from main.


view run

@Krishna2323

Copy link
Copy Markdown
Contributor Author

@JmillsExpensify @JS00001 @dubielzyk-expensify found an issue while testing this:

Issue: We can currently enable Require tags from Rules even when the workspace has no tags. Enabling Tags only enables the tags page with an empty tag list, so this leaves us with an invalid state where every expense gets a tag violation.

Proposed fix: Don't enable Tags from the Rules page.

  1. If Tags is off, the modal sends the admin to More features to enable it.
  2. If Tags is on but empty, keep Require tags disabled with a tooltip: "You don't have any tags. Please create a tag."
  3. Once a tag exists, the toggle becomes available and the admin can enable it.

This avoids writing an impossible "require tags" state and removes the need for hidden state/cleanup.

Things to confirm:

  • Keep the current one-tap flow when tags already exist, or always send to More features?
  • Should Categories follow the same pattern?
Monosnap.screencast.2026-08-19.22-12-42.mp4

@JmillsExpensify

Copy link
Copy Markdown
Contributor

Enabling Tags only enables the tags page with an empty tag list, so this leaves us with an invalid state where every expense gets a tag violation.

Wouldn't this only be the case when you add a tag and then subsequently create expenses? Or are you saying that we show an empty tag field as required, and there is no way to resolve it?

@Krishna2323

Krishna2323 commented Aug 19, 2026

Copy link
Copy Markdown
Contributor Author

Wouldn't this only be the case when you add a tag and then subsequently create expenses? Or are you saying that we show an empty tag field as required, and there is no way to resolve it?

Ahh, you're right. I overstated that. No violation fires in this state, so there's no unresolvable field. Sorry for the noise.

The actual issue is narrower:

  • The admin can't tell what happened. The toggle shows on with a lock, does nothing when tapped, and has no tooltip. After reopening, it's off.

I'd suggest we stop enabling Tags from the Rules page. The modal should send them to More features to enable Tags. Then, if Tags is enabled but empty, keep Require tags disabled with: "You don't have any tags. Please create a tag." Once a tag exists, they can enable it normally.

If you have any other ideas, please let me know. One thing I'd suggest updating anyway: if the toggle is locked because there are no categories/tags, we should show a tooltip explaining why it's disabled.

@JmillsExpensify

Copy link
Copy Markdown
Contributor

I'd suggest we stop enabling Tags from the Rules page. The modal should send them to More features to enable Tags. Then, if Tags is enabled but empty, keep Require tags disabled with: "You don't have any tags. Please create a tag." Once a tag exists, they can enable it normally.

Given that we are cool if they enable tags but don't create any, why wouldn't we:

  • Allow them to enable tags from Rules
  • If they enable tags from Rules, or even if they enabled them elsewhere, if they have none then show the tooltip

Signed-off-by: krishna2323 <belivethatkg@gmail.com>
@melvin-bot

melvin-bot Bot commented Aug 20, 2026

Copy link
Copy Markdown

Hey, I noticed you changed src/languages/en.ts in a PR from a fork. For security reasons, translations are not generated automatically for PRs from forks.

If you want to automatically generate translations for other locales, an Expensify employee will have to:

  1. Look at the code and make sure there are no malicious changes.
  2. Run the Generate static translations GitHub workflow. If you have write access and the K2 extension, you can simply click: [this button]

Alternatively, if you are an external contributor, you can run the translation script locally with your own OpenAI API key. To learn more, try running:

npx bun ./scripts/generateTranslations.ts --help

Typically, you'd want to translate only what you changed by running npx bun ./scripts/generateTranslations.ts --compare-ref main

Signed-off-by: krishna2323 <belivethatkg@gmail.com>
@Krishna2323

Copy link
Copy Markdown
Contributor Author

@JmillsExpensify

Made the changes:

  • Tags: The Rules modal now only enables the Tags feature. It no longer sets Require tags. The admin can turn that on once a tag exists.
  • Categories: This turned out to be a BE issue. BE sets requiresCategory: true whenever categories are enabled, even when the workspace has no categories. I tried fixing it on FE, but reverted it since we'd just be fighting the server value.

@JS00001 Can we skip setting requiresCategory on ENABLE_POLICY_CATEGORIES when the workspace has no categories? Requiring a category that doesn't exist can't be satisfied, and missingCategory isn't gated on categories existing like missingTag is on enabled tags (ViolationsUtils.ts:557). So right now it flags every expense with no way to clear it.

Copy to confirm. Only the Tags modal prompt and the two tooltips are new:

Where Copy Shows when
Tags modal "Enable tags?" / "Are you sure you want to enable tags? You can require them for all expenses once you have at least one tag." Tapping locked Require tags, Tags off
Categories modal "Enable categories?" / "Are you sure you want to enable categories and require them for all expenses?" Tapping locked Require categories, Categories off
Tags tooltip "You don't have any tags. Please create a tag." Tags on, no enabled tags
Categories tooltip "You don't have any categories. Please create a category." Categories on, no enabled categories

The categories tooltip still helps in the meantime since the toggle is at least explained when there's nothing to require.

I don't think we need to block on the category issue since it also happens in production.

Category require issue on staging:

Monosnap.screencast.2026-08-20.17-59-54.mp4

Rules revamp page (This PR):

Monosnap.screencast.2026-08-20.18-01-06.mp4

@JS00001

JS00001 commented Aug 20, 2026

Copy link
Copy Markdown
Contributor

I think that makes sense, yes

Signed-off-by: krishna2323 <belivethatkg@gmail.com>
@Krishna2323

Copy link
Copy Markdown
Contributor Author

@situchan this one is ready for code review.

@JmillsExpensify

Copy link
Copy Markdown
Contributor

All looks good to me!

@Krishna2323

Copy link
Copy Markdown
Contributor Author

@JS00001 please run the translations script when you get a chance 🙏

@OSBotify

This comment has been minimized.

@dylanexpensify

Copy link
Copy Markdown
Contributor

@Krishna2323 ran

@OSBotify

Copy link
Copy Markdown
Contributor

🦜 Polyglot Parrot! 🦜

Squawk! Looks like you added some shiny new English strings. Allow me to parrot them back to you in other tongues:

View the translation diff
diff --git a/src/languages/de.ts b/src/languages/de.ts
index 3018a441..7a30e67d 100644
--- a/src/languages/de.ts
+++ b/src/languages/de.ts
@@ -7732,6 +7732,9 @@ Fordern Sie Spesendetails wie Belege und Beschreibungen an, legen Sie Limits und
                 enableCategoriesToUnlockTitle: 'Kategorien aktivieren?',
                 enableCategoriesToUnlockPrompt: 'Aktivieren Sie Kategorien (unter Weitere Funktionen), um dies freizuschalten.',
                 enableCategoriesAndRequirePrompt: 'Sind Sie sicher, dass Sie Kategorien aktivieren und für alle Ausgaben verpflichtend machen möchten?',
+                enableTagsPrompt: 'Möchten Sie Tags wirklich aktivieren? Sie können sie für alle Ausgaben erforderlich machen, sobald Sie mindestens einen Tag haben.',
+                noTagsToRequirePrompt: 'Sie haben keine Tags. Bitte erstellen Sie einen Tag.',
+                noCategoriesToRequirePrompt: 'Sie haben keine Kategorien. Bitte erstellen Sie eine Kategorie.',
             },
             expenseReportRules: {
                 title: 'Erweitert',
diff --git a/src/languages/el.ts b/src/languages/el.ts
index 5e18b02f..7d9f6695 100644
--- a/src/languages/el.ts
+++ b/src/languages/el.ts
@@ -8056,6 +8056,9 @@ ${reportName}`,
                 enableCategoriesToUnlockTitle: 'Ενεργοποίηση κατηγοριών;',
                 enableCategoriesToUnlockPrompt: 'Ενεργοποιήστε τις κατηγορίες (στην ενότητα «Περισσότερες λειτουργίες») για να τις ξεκλειδώσετε.',
                 enableCategoriesAndRequirePrompt: 'Είστε βέβαιοι ότι θέλετε να ενεργοποιήσετε τις κατηγορίες και να τις απαιτείτε για όλες τις δαπάνες;',
+                enableTagsPrompt: 'Είστε βέβαιοι ότι θέλετε να ενεργοποιήσετε τις ετικέτες; Μπορείτε να τις κάνετε υποχρεωτικές για όλες τις δαπάνες μόλις έχετε τουλάχιστον μία ετικέτα.',
+                noTagsToRequirePrompt: 'Δεν έχετε ετικέτες. Δημιουργήστε μία ετικέτα.',
+                noCategoriesToRequirePrompt: 'Δεν έχετε κατηγορίες. Δημιουργήστε μια κατηγορία.',
             },
             expenseReportRules: {
                 title: 'Για προχωρημένους',
diff --git a/src/languages/es.ts b/src/languages/es.ts
index 751a1603..62ba9a0d 100644
--- a/src/languages/es.ts
+++ b/src/languages/es.ts
@@ -7704,6 +7704,9 @@ El plan Controlar empieza en 9 $ por miembro activo al mes.`,
                 enableCategoriesToUnlockTitle: '¿Habilitar categorías?',
                 enableCategoriesToUnlockPrompt: 'Activa Categorías (en Más funciones) para desbloquear.',
                 enableCategoriesAndRequirePrompt: '¿Seguro que quieres habilitar las categorías y hacerlas obligatorias para todos los gastos?',
+                enableTagsPrompt: '¿Seguro que quieres habilitar las etiquetas? Podrás exigirlas para todos los gastos cuando tengas al menos una etiqueta.',
+                noTagsToRequirePrompt: 'No tienes ninguna etiqueta. Por favor, crea una etiqueta.',
+                noCategoriesToRequirePrompt: 'No tienes ninguna categoría. Por favor, crea una categoría.',
             },
             expenseReportRules: {
                 title: 'Avanzado',
diff --git a/src/languages/fr.ts b/src/languages/fr.ts
index c80d2075..cc330e79 100644
--- a/src/languages/fr.ts
+++ b/src/languages/fr.ts
@@ -7755,6 +7755,9 @@ Rendez obligatoires des informations de dépense comme les reçus et les descrip
                 enableCategoriesToUnlockTitle: 'Activer les catégories ?',
                 enableCategoriesToUnlockPrompt: 'Activez les catégories (dans Plus de fonctionnalités) pour déverrouiller.',
                 enableCategoriesAndRequirePrompt: 'Voulez-vous vraiment activer les catégories et les rendre obligatoires pour toutes les dépenses ?',
+                enableTagsPrompt: 'Voulez-vous vraiment activer les tags ? Vous pourrez les rendre obligatoires pour toutes les dépenses une fois que vous aurez au moins un tag.',
+                noTagsToRequirePrompt: "Vous n'avez aucun tag. Veuillez créer un tag.",
+                noCategoriesToRequirePrompt: 'Vous n’avez aucune catégorie. Veuillez créer une catégorie.',
             },
             expenseReportRules: {
                 title: 'Avancé',
diff --git a/src/languages/it.ts b/src/languages/it.ts
index bfbc613b..950cdc93 100644
--- a/src/languages/it.ts
+++ b/src/languages/it.ts
@@ -7699,6 +7699,9 @@ Richiedi dettagli sulle spese come ricevute e descrizioni, imposta limiti e valo
                 enableCategoriesToUnlockTitle: 'Abilitare le categorie?',
                 enableCategoriesToUnlockPrompt: 'Attiva Categorie (in Altre funzionalità) per sbloccare.',
                 enableCategoriesAndRequirePrompt: 'Sei sicuro di voler abilitare le categorie e renderle obbligatorie per tutte le spese?',
+                enableTagsPrompt: 'Sei sicuro di voler abilitare i tag? Potrai renderli obbligatori per tutte le spese non appena avrai almeno un tag.',
+                noTagsToRequirePrompt: 'Non hai ancora nessun tag. Crea un tag.',
+                noCategoriesToRequirePrompt: 'Non hai ancora nessuna categoria. Crea una categoria.',
             },
             expenseReportRules: {
                 title: 'Avanzate',
diff --git a/src/languages/ja.ts b/src/languages/ja.ts
index 34ab98b2..6be61722 100644
--- a/src/languages/ja.ts
+++ b/src/languages/ja.ts
@@ -7606,6 +7606,9 @@ ${reportName}`,
                 enableCategoriesToUnlockTitle: 'カテゴリーを有効にしますか?',
                 enableCategoriesToUnlockPrompt: 'ロックを解除するには、[その他の機能]で[カテゴリ]を有効にしてください。',
                 enableCategoriesAndRequirePrompt: 'カテゴリを有効にし、すべての経費でカテゴリを必須にしてもよろしいですか?',
+                enableTagsPrompt: 'タグを有効にしてもよろしいですか?タグが少なくとも1つある場合、すべての経費でタグの入力を必須にできます。',
+                noTagsToRequirePrompt: 'タグがありません。タグを作成してください。',
+                noCategoriesToRequirePrompt: 'カテゴリがありません。カテゴリを作成してください。',
             },
             expenseReportRules: {
                 title: '詳細設定',
diff --git a/src/languages/nl.ts b/src/languages/nl.ts
index 8cf7d84a..0f05e2e9 100644
--- a/src/languages/nl.ts
+++ b/src/languages/nl.ts
@@ -7680,6 +7680,9 @@ Vereis onkostendetails zoals bonnen en beschrijvingen, stel limieten en standaar
                 enableCategoriesToUnlockTitle: 'Categorieën inschakelen?',
                 enableCategoriesToUnlockPrompt: 'Schakel Categorieën (onder Meer functies) in om te ontgrendelen.',
                 enableCategoriesAndRequirePrompt: 'Weet je zeker dat je categorieën wilt inschakelen en ze verplicht wilt maken voor alle uitgaven?',
+                enableTagsPrompt: 'Weet je zeker dat je labels wilt inschakelen? Je kunt ze verplicht maken voor alle uitgaven zodra je minstens één label hebt.',
+                noTagsToRequirePrompt: 'Je hebt nog geen tags. Maak alsjeblieft een tag aan.',
+                noCategoriesToRequirePrompt: 'Je hebt nog geen categorieën. Maak een categorie aan.',
             },
             expenseReportRules: {
                 title: 'Geavanceerd',
diff --git a/src/languages/pl.ts b/src/languages/pl.ts
index c11c9754..954a64f7 100644
--- a/src/languages/pl.ts
+++ b/src/languages/pl.ts
@@ -7664,6 +7664,9 @@ Wymagaj szczegółów wydatków, takich jak paragony i opisy, ustawiaj limity i
                 enableCategoriesToUnlockTitle: 'Włączyć kategorie?',
                 enableCategoriesToUnlockPrompt: 'Włącz Kategorie (w sekcji Więcej funkcji), aby odblokować.',
                 enableCategoriesAndRequirePrompt: 'Na pewno chcesz włączyć kategorie i wymagać ich dla wszystkich wydatków?',
+                enableTagsPrompt: 'Na pewno chcesz włączyć tagi? Będziesz mógł wymagać ich dla wszystkich wydatków, gdy będziesz mieć co najmniej jeden tag.',
+                noTagsToRequirePrompt: 'Nie masz żadnych tagów. Utwórz tag.',
+                noCategoriesToRequirePrompt: 'Nie masz żadnych kategorii. Utwórz kategorię.',
             },
             expenseReportRules: {
                 title: 'Zaawansowane',
diff --git a/src/languages/pt-BR.ts b/src/languages/pt-BR.ts
index a7651f5a..8e1c2cbb 100644
--- a/src/languages/pt-BR.ts
+++ b/src/languages/pt-BR.ts
@@ -7682,6 +7682,9 @@ Exija dados de despesas como recibos e descrições, defina limites e padrões e
                 enableCategoriesToUnlockTitle: 'Ativar categorias?',
                 enableCategoriesToUnlockPrompt: 'Ative Categorias (em Mais recursos) para desbloquear.',
                 enableCategoriesAndRequirePrompt: 'Tem certeza de que deseja ativar categorias e torná-las obrigatórias para todas as despesas?',
+                enableTagsPrompt: 'Tem certeza de que quer ativar tags? Você poderá exigi-las para todas as despesas assim que tiver pelo menos uma tag.',
+                noTagsToRequirePrompt: 'Você não tem nenhuma tag. Crie uma tag.',
+                noCategoriesToRequirePrompt: 'Você não tem nenhuma categoria. Crie uma categoria.',
             },
             expenseReportRules: {
                 title: 'Avançado',
diff --git a/src/languages/zh-hans.ts b/src/languages/zh-hans.ts
index 7924e631..9bb171f4 100644
--- a/src/languages/zh-hans.ts
+++ b/src/languages/zh-hans.ts
@@ -7422,6 +7422,9 @@ ${reportName}`,
                 enableCategoriesToUnlockTitle: '启用类别?',
                 enableCategoriesToUnlockPrompt: '启用“类别”(位于“更多功能”下)以解锁。',
                 enableCategoriesAndRequirePrompt: '确定要启用类别,并要求所有报销都必须选择类别吗?',
+                enableTagsPrompt: '确定要启用标签吗?在至少有一个标签后,您可以要求所有报销都必须选择标签。',
+                noTagsToRequirePrompt: '您还没有任何标签。请创建一个标签。',
+                noCategoriesToRequirePrompt: '您还没有任何类别。请创建一个类别。',
             },
             expenseReportRules: {
                 title: '高级',

Note

You can apply these changes to your branch by copying the patch to your clipboard, then running pbpaste | git apply 😉

View workflow run

Signed-off-by: krishna2323 <belivethatkg@gmail.com>
Signed-off-by: krishna2323 <belivethatkg@gmail.com>
Signed-off-by: krishna2323 <belivethatkg@gmail.com>
@situchan

situchan commented Aug 21, 2026

Copy link
Copy Markdown
Contributor

Reviewer Checklist

  • I have verified the author checklist is complete (all boxes are checked off).
  • I verified the correct issue is linked in the ### Fixed Issues section above
  • I verified testing steps are clear and they cover the changes made in this PR
    • I verified the steps for local testing are in the Tests section
    • I verified the steps for Staging and/or Production testing are in the QA steps section
    • I verified the steps cover any possible failure scenarios (i.e. verify an input displays the correct error message if the entered data is not correct)
    • I turned off my network connection and tested it while offline to ensure it matches the expected behavior (i.e. verify the default avatar icon is displayed if app is offline)
  • I checked that screenshots or videos are included for tests on all platforms
  • I included screenshots or videos for tests on all platforms
  • I verified that the composer does not automatically focus or open the keyboard on mobile unless explicitly intended. This includes checking that returning the app from the background does not unexpectedly open the keyboard.
  • I verified tests pass on all platforms & I tested again on:
    • Android: HybridApp
    • Android: mWeb Chrome
    • iOS: HybridApp
    • iOS: mWeb Safari
    • MacOS: Chrome / Safari
  • If there are any errors in the console that are unrelated to this PR, I either fixed them (preferred) or linked to where I reported them in Slack
  • I verified proper code patterns were followed (see Reviewing the code)
    • I verified that any callback methods that were added or modified are named for what the method does and never what callback they handle (i.e. toggleReport and not onIconClick).
    • I verified that comments were added to code that is not self explanatory
    • I verified that any new or modified comments were clear, correct English, and explained "why" the code was doing something instead of only explaining "what" the code was doing.
    • I verified any copy / text that was added to the app is grammatically correct in English. It adheres to proper capitalization guidelines (note: only the first word of header/labels should be capitalized), and is either coming verbatim from figma or has been approved by marketing (in order to get marketing approval, ask the Bug Zero team member to add the Waiting for copy label to the issue)
  • If a new code pattern is added I verified it was agreed to be used by multiple Expensify engineers
  • I verified that this PR follows the guidelines as stated in the Review Guidelines
  • I verified other components that can be impacted by these changes have been tested, and I retested again (i.e. if the PR modifies a shared library or component like Avatar, I verified the components using Avatar have been tested & I retested again)
  • If a new component is created I verified that:
    • A similar component doesn't exist in the codebase
    • All props are defined accurately and each prop has a /** comment above it */
    • The file is named correctly
    • The component has a clear name that is non-ambiguous and the purpose of the component can be inferred from the name alone
    • The only data being stored in the state is data necessary for rendering and nothing else
    • For Class Components, any internal methods passed to components event handlers are bound to this properly so there are no scoping issues (i.e. for onClick={this.submit} the method this.submit should be bound to this in the constructor)
    • Any internal methods bound to this are necessary to be bound (i.e. avoid this.submit = this.submit.bind(this); if this.submit is never passed to a component event handler like onClick)
    • All JSX used for rendering exists in the render method
    • The component has the minimum amount of code necessary for its purpose, and it is broken down into smaller components in order to separate concerns and functions
  • If any new file was added I verified that:
    • The file has a description of what it does and/or why is needed at the top of the file if the code is not self explanatory
  • If a new CSS style is added I verified that:
    • A similar style doesn't already exist
    • The style can't be created with an existing StyleUtils function (i.e. StyleUtils.getBackgroundAndBorderStyle(theme.componentBG)
  • If the PR modifies code that runs when editing or sending messages, I tested and verified there is no unexpected behavior for all supported markdown - URLs, single line code, code blocks, quotes, headings, bold, strikethrough, and italic.
  • If the PR modifies a generic component, I tested and verified that those changes do not break usages of that component in the rest of the App (i.e. if a shared library or component like Avatar is modified, I verified that Avatar is working as expected in all cases)
  • If the PR modifies a component related to any of the existing Storybook stories, I tested and verified all stories for that component are still working as expected.
  • If the PR modifies a component or page that can be accessed by a direct deeplink, I verified that the code functions as expected when the deeplink is used - from a logged in and logged out account.
  • If the PR modifies the UI (e.g. new buttons, new UI components, changing the padding/spacing/sizing, moving components, etc) or modifies the form input styles:
    • I verified that all the inputs inside a form are aligned with each other.
    • I added Design label and/or tagged @Expensify/design so the design team can review the changes.
  • For any bug fix or new feature in this PR, I verified that sufficient unit tests are included to prevent regressions in this flow.
  • If the main branch was merged into this PR after a review, I tested again and verified the outcome was still expected according to the Test steps.
  • I have checked off every checkbox in the PR reviewer checklist, including those that don't apply to this PR.

Screenshots/Videos

Android: HybridApp
Android: mWeb Chrome
iOS: HybridApp
iOS: mWeb Safari
MacOS: Chrome / Safari
web.mov

Comment thread src/pages/workspace/rules/RulesProhibitedDefaultPage.tsx
Comment thread src/pages/workspace/WorkspaceMoreFeaturesPage/index.tsx
Comment thread src/pages/workspace/rules/RulesRequireFieldsPage.tsx
Comment thread src/pages/workspace/tags/WorkspaceTagsPage.tsx Outdated
Comment thread src/pages/workspace/WorkspaceMoreFeaturesPage/index.tsx
@situchan

situchan commented Aug 21, 2026

Copy link
Copy Markdown
Contributor

#98699 failing on iOS

Screen.Recording.2026-08-21.at.12.54.35.PM.mov

@situchan

Copy link
Copy Markdown
Contributor

Same bug happens in other page:

Screen.Recording.2026-08-21.at.1.28.04.PM.mov

Comment thread src/pages/workspace/rules/PolicyRulesPage.tsx
Comment thread src/pages/workspace/rules/RulesBillableDefaultPage.tsx
Comment thread src/pages/workspace/rules/RulesBillableDefaultPage.tsx Outdated
Comment thread src/pages/workspace/workflows/WorkspaceWorkflowsPage.tsx Outdated
Signed-off-by: krishna2323 <belivethatkg@gmail.com>
Signed-off-by: krishna2323 <belivethatkg@gmail.com>
@Krishna2323

Copy link
Copy Markdown
Contributor Author

#98699 failing on iOS

@situchan fixed:

Monosnap.screencast.2026-08-21.21-17-29.mp4

Signed-off-by: krishna2323 <belivethatkg@gmail.com>
@JS00001 JS00001 changed the title remove rulesRevamp beta. [hold] remove rulesRevamp beta. Aug 21, 2026
@JS00001

JS00001 commented Aug 21, 2026

Copy link
Copy Markdown
Contributor

@Krishna2323 @situchan lets hold this PR for now. We forgot to add category tax defaults to the new rules flow. @JmillsExpensify will work on ironing out the details for this so we can finish that up monday

@luacmartins
luacmartins self-requested a review August 21, 2026 17:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants