Skip to content

[Due for payment 2026-03-24] Workspace settings - Not here page shown when navigate to Per Diem from the workspace editor #80872

Closed

Description

@izarutskaya

If you haven’t already, check out our contributing guidelines for onboarding and email contributors@expensify.com to request to join our Slack channel!


Version Number:
Reproducible in staging?: Needs Reproduction. The steps described could not be executed ( missing details)
Reproducible in production?: Needs Reproduction
If this was caught during regression testing, add the test name, ID and link from BrowserStack:
Email or phone of affected tester (no customers):
Logs: https://stackoverflow.com/c/expensify/questions/4856
Expensify/Expensify Issue URL:
Issue reported by: @shawnborton
Slack conversation (hyperlinked to channel name): #expensify_bugs

Action Performed:

Prerequisite: Needs account with Collect workspace and Per Diem feature enabled

  1. Log in https://staging.new.expensify.com/
  2. Go to the workspace (in Prerequisite) > navigate to Per Diem page

Expected Result:

User sees the correct page and can continue working to import rates from a spreadsheet.

Actual Result:

Not here page shown when navigate to Per Diem page.

Workaround:

Unknown

Platforms:

Select the officially supported platforms where the issue was reproduced:

  • Android: App
  • Android: mWeb Chrome
  • iOS: App
  • iOS: mWeb Safari
  • iOS: mWeb Chrome
  • Windows: Chrome
  • MacOS: Chrome / Safari

Screenshots/Videos

Image

View all open jobs on GitHub

Issue OwnerCurrent Issue Owner: @truph01

Activity

  1. added
    ExternalAdded to denote the issue can be worked on by a contributor
    BugSomething is broken. Auto assigns a BugZero manager.
    on Jan 29, 2026
  2. added
    Help WantedApply this label when an issue is open to proposals by contributors
    on Jan 29, 2026
  3. melvin-bot commented on Jan 29, 2026

    @melvin-bot

    Triggered auto assignment to Contributor-plus team member for initial proposal review - @QichenZhu (External)

  4. melvin-bot commented on Jan 29, 2026

    @melvin-bot

    Triggered auto assignment to @kadiealexander (Bug), see https://stackoverflow.com/c/expensify/questions/14418 for more details. Please add this bug to a GH project, as outlined in the SO.

  5. MelvinBot commented on Jan 29, 2026

    @MelvinBot
    Contributor

    This has been labelled "Needs Reproduction". Follow the steps here: https://stackoverflowteams.com/c/expensify/questions/16989

  6. daledah commented on Jan 29, 2026

    @daledah
    Contributor

    Proposal

    Please re-state the problem that we are trying to solve in this issue.

    When navigating to the Per Diem page on a Collect workspace with the Per Diem feature enabled, users see the "Not here" page instead of the correct Per Diem page.

    What is the root cause of that problem?

    The root cause is that the WorkspacePerDiemPage (and all related Per Diem pages) use an overly restrictive access check that requires the policy to be a Control policy type:

    <AccessOrNotFoundWrapper
    accessVariants={[CONST.POLICY.ACCESS_VARIANTS.ADMIN, CONST.POLICY.ACCESS_VARIANTS.CONTROL]}
    policyID={policyID}
    featureName={CONST.POLICY.MORE_FEATURES.ARE_PER_DIEM_RATES_ENABLED}

    The AccessOrNotFoundWrapper combines all access variants with AND logic:

    const isPageAccessible = accessVariants.reduce((acc, variant) => {
    const accessFunction = ACCESS_VARIANTS[variant];
    if (variant === CONST.IOU.ACCESS_VARIANTS.CREATE) {
    return acc && accessFunction(policy, login, report, allPolicies ?? null, iouType, isReportArchived, isRestrictedToPreferredPolicy);
    }
    return acc && accessFunction(policy, login, report, allPolicies ?? null, iouType, isReportArchived);
    }, true);

    The access variants map:

    const ACCESS_VARIANTS = {
    [CONST.POLICY.ACCESS_VARIANTS.PAID]: (policy: OnyxEntry<Policy>) => isPaidGroupPolicy(policy),
    [CONST.POLICY.ACCESS_VARIANTS.CONTROL]: (policy: OnyxEntry<Policy>) => isControlPolicy(policy),
    [CONST.POLICY.ACCESS_VARIANTS.ADMIN]: (policy: OnyxEntry<Policy>, login: string) => isPolicyAdmin(policy, login),

    When accessVariants={[ADMIN, CONTROL]}:

    • ADMIN check passes (user is admin)
    • CONTROL check fails (policy is Collect/TEAM type, not Control/CORPORATE)
    • Result: Page shows "Not here"

    The issue is that CONTROL checks for policy?.type === CONST.POLICY.TYPE.CORPORATE only, which excludes Collect workspaces (policy?.type === CONST.POLICY.TYPE.TEAM).

    What changes do you think we should make in order to solve the problem?

    Change the access variant from CONTROL to PAID in all Per Diem pages. The PAID variant allows both Collect (TEAM) and Control (CORPORATE) policy types:

    WorkspacePerDiemPage.tsx:

    <AccessOrNotFoundWrapper
    -   accessVariants={[CONST.POLICY.ACCESS_VARIANTS.ADMIN, CONST.POLICY.ACCESS_VARIANTS.CONTROL]}
    +   accessVariants={[CONST.POLICY.ACCESS_VARIANTS.ADMIN, CONST.POLICY.ACCESS_VARIANTS.PAID]}
        policyID={policyID}
        featureName={CONST.POLICY.MORE_FEATURES.ARE_PER_DIEM_RATES_ENABLED}
    >

    Apply the same change to all Per Diem related pages:

    • WorkspacePerDiemPage.tsx
    • WorkspacePerDiemDetailsPage.tsx
    • WorkspacePerDiemSettingsPage.tsx
    • EditPerDiemAmountPage.tsx
    • EditPerDiemCurrencyPage.tsx
    • EditPerDiemDestinationPage.tsx
    • EditPerDiemSubratePage.tsx
    • ImportPerDiemPage.tsx
    • ImportedPerDiemPage.tsx

    The featureName={CONST.POLICY.MORE_FEATURES.ARE_PER_DIEM_RATES_ENABLED} check will still ensure that the feature is actually enabled on the workspace, so users won't have access unless arePerDiemRatesEnabled is true.

    What alternative solutions did you explore? (Optional)

    1. Keep Per Diem as Control-only: If Per Diem is intended to be a Control-only feature, the fix should be in WorkspaceMoreFeaturesPage.tsx to prevent showing/navigating to Per Diem on Collect workspaces when the feature is somehow enabled. However, this would break existing Collect workspaces that have Per Diem enabled.

    2. Fix at the data level: Ensure arePerDiemRatesEnabled cannot be true for Collect workspaces. This would be a backend change and might break existing data.

  7. QichenZhu commented on Jan 29, 2026

    @QichenZhu
    Contributor

    The root cause is that the WorkspacePerDiemPage (and all related Per Diem pages) use an overly restrictive access check that requires the policy to be a Control policy type:

    This restriction is expected, not the root cause.

  8. truph01 commented on Jan 29, 2026

    @truph01
    Contributor

    Proposal

    Please re-state the problem that we are trying to solve in this issue.

    • The "Not Here" page is incorrectly shown when navigating to the Per Diem page, even though the feature appears to be enabled.

    What is the root cause of that problem?

    • The display of the Per Diem feature on the initial workspace page is controlled by this check:
      [CONST.POLICY.MORE_FEATURES.ARE_PER_DIEM_RATES_ENABLED]: policy?.arePerDiemRatesEnabled,
    • However, the actual visibility of the Per Diem page also depends on whether the user is on a valid plan. This is enforced here:
      accessVariants={[CONST.POLICY.ACCESS_VARIANTS.ADMIN, CONST.POLICY.ACCESS_VARIANTS.CONTROL]}
    • Because these conditions are not aligned, the UI may show the entry point for Per Diem even when the user cannot access the page, resulting in a confusing experience.

    What changes do you think we should make in order to solve the problem?

    • Introduce a utility function to centralize access control for feature visibility based on plan level. Example implementation:
    const CORPORATE_ONLY_FEATURES: PolicyFeatureName[] = [
        CONST.POLICY.MORE_FEATURES.ARE_RULES_ENABLED,
        CONST.POLICY.MORE_FEATURES.ARE_PER_DIEM_RATES_ENABLED,
    ]; // This list can be expanded as needed.
    
    function canPolicyAccessFeature(policy: OnyxEntry<Policy>, featureName: PolicyFeatureName): boolean {
    
        if (!isPaidGroupPolicy(policy)) {
            return false;
        }
    
        if (CORPORATE_ONLY_FEATURES.includes(featureName)) {
            return isControlPolicy(policy);
        }
    
        return true;
    }
                [CONST.POLICY.MORE_FEATURES.ARE_PER_DIEM_RATES_ENABLED]:
                    policy?.arePerDiemRatesEnabled && canPolicyAccessFeature(policy, CONST.POLICY.MORE_FEATURES.ARE_PER_DIEM_RATES_ENABLED),
    • Apply the same logic to other features where similar plan-based gating is required to maintain consistent behavior across the app.

    What alternative solutions did you explore? (Optional)

    • Optimistically update the policy.arePerDiemRatesEnabled (and other features which are only available in control) when downgrading in
      function downgradeToTeam(policyID: string) {
  9. QichenZhu commented on Jan 29, 2026

    @QichenZhu
    Contributor

    @truph01, I can't reproduce this issue. Do you have reliable steps? Another C+ can comment and take over if they can.

  10. 27 remaining items

  11. melvin-bot commented on Mar 17, 2026

    @melvin-bot

    Reviewing label has been removed, please complete the "BugZero Checklist".

  12. melvin-bot commented on Mar 17, 2026

    @melvin-bot

    The solution for this issue has been 🚀 deployed to production 🚀 in version 9.3.38-4 and is now subject to a 7-day regression period 📆. Here is the list of pull requests that resolve this issue:

    If no regressions arise, payment will be issued on 2026-03-24. 🎊

    For reference, here are some details about the assignees on this issue:

    • @QichenZhu requires payment through NewDot Manual Requests
    • @truph01 requires payment through NewDot Manual Requests
  13. melvin-bot commented on Mar 17, 2026

    @melvin-bot

    @QichenZhu / @truph01 The PR fixing this issue has been merged! The following checklist (instructions) will need to be completed before the issue can be closed. Please copy/paste the BugZero Checklist from here into a new comment on this GH and complete it. If you have the K2 extension, you can simply click: [this button]

  14. melvin-bot commented on Mar 17, 2026

    @melvin-bot

    Triggered auto assignment to @mallenexpensify (Awaiting Payment)

  15. QichenZhu commented on Mar 24, 2026

    @QichenZhu
    Contributor

    BugZero Checklist:

    • [Contributor] The offending PR has been commented on, pointing out the bug it caused and why, so the author and reviewers can learn from the mistake.

      Link to comment: N/A. This special requirement was overlooked.

    • [Contributor] If the regression was CRITICAL (e.g. interrupts a core flow) A discussion in #expensify-open-source has been started about whether any other steps should be taken (e.g. updating the PR review checklist) in order to catch this type of bug sooner.

      Link to discussion: N/A.

    • [Contributor] If it was decided to create a regression test for the bug, please propose the regression test steps using the template below to ensure the same bug will not reach production again.

      I don't think there is a reliable way to test this, since it applies only to some old accounts that had Per Diem enabled in a collect workspace before the feature became limited to control policies.

  16. mallenexpensify commented on Mar 24, 2026

    @mallenexpensify
    Contributor

    Payment Summary

    Contributor: @truph01 due $250 via NewDot
    Contributor+: @QichenZhu due $250 via NewDot

    I don't think there is a reliable way to test this, since it applies only to some old accounts that had Per Diem enabled in a collect workspace before the feature became limited to control policies.

    👍

  17. twisterdotcom commented on Mar 26, 2026

    @twisterdotcom
    Contributor

    @QichenZhu has submitted payment for this report on ND here.

    SO: https://stackoverflowteams.com/c/expensify/questions/7582

    Zapier Logs Run ID: 00040eee-0dc9-a695-4b5d-3f75861e6964
  18. garrettmknight commented on May 22, 2026

    @garrettmknight
    Contributor

    $250 approved for @truph01

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

Awaiting PaymentAuto-added when associated PR is deployed to productionBugSomething is broken. Auto assigns a BugZero manager.DailyKSv2ExternalAdded to denote the issue can be worked on by a contributorNeeds ReproductionReproducible steps needed

Type

No type

Projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions