Skip to content

Commit

Permalink
Merge pull request #45540 from Expensify/Rory-FixAutoReportingToggle
Browse files Browse the repository at this point in the history
Fix auto reporting toggle
  • Loading branch information
Beamanator authored Jul 17, 2024
2 parents c82183b + ad6cbeb commit ebe7d58
Show file tree
Hide file tree
Showing 8 changed files with 79 additions and 22 deletions.
3 changes: 2 additions & 1 deletion src/libs/NextStepUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,8 @@ function buildNextStep(report: OnyxEntry<Report>, predictedNextStatus: ValueOf<t

const {policyID = '', ownerAccountID = -1, managerID = -1} = report ?? {};
const policy = allPolicies?.[`${ONYXKEYS.COLLECTION.POLICY}${policyID}`] ?? ({} as Policy);
const {harvesting, preventSelfApproval, autoReportingFrequency, autoReportingOffset} = policy;
const {harvesting, preventSelfApproval, autoReportingOffset} = policy;
const autoReportingFrequency = PolicyUtils.getCorrectedAutoReportingFrequency(policy);
const submitToAccountID = PolicyUtils.getSubmitToAccountID(policy, ownerAccountID);
const isOwner = currentUserAccountID === ownerAccountID;
const isManager = currentUserAccountID === managerID;
Expand Down
24 changes: 24 additions & 0 deletions src/libs/PolicyUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -340,6 +340,29 @@ function isInstantSubmitEnabled(policy: OnyxInputOrEntry<Policy>): boolean {
return policy?.type === CONST.POLICY.TYPE.FREE || (policy?.autoReporting === true && policy?.autoReportingFrequency === CONST.POLICY.AUTO_REPORTING_FREQUENCIES.INSTANT);
}

/**
* This gets a "corrected" value for autoReportingFrequency. The purpose of this function is to encapsulate some logic around the "immediate" frequency.
*
* - "immediate" is actually not immediate. For that you want "instant".
* - (immediate && harvesting.enabled) === daily
* - (immediate && !harvesting.enabled) === manual
*
* Note that "daily" and "manual" only exist as options for the API, not in the database or Onyx.
*/
function getCorrectedAutoReportingFrequency(policy: OnyxInputOrEntry<Policy>): ValueOf<typeof CONST.POLICY.AUTO_REPORTING_FREQUENCIES> | undefined {
if (policy?.autoReportingFrequency !== CONST.POLICY.AUTO_REPORTING_FREQUENCIES.IMMEDIATE) {
return policy?.autoReportingFrequency;
}

if (policy?.harvesting?.enabled) {
// This is actually not really "immediate". It's "daily". Surprise!
return CONST.POLICY.AUTO_REPORTING_FREQUENCIES.IMMEDIATE;
}

// "manual" is really just "immediate" (aka "daily") with harvesting disabled
return CONST.POLICY.AUTO_REPORTING_FREQUENCIES.MANUAL;
}

/**
* Checks if policy's approval mode is "optional", a.k.a. "Submit & Close"
*/
Expand Down Expand Up @@ -793,6 +816,7 @@ export {
isDeletedPolicyEmployee,
isFreeGroupPolicy,
isInstantSubmitEnabled,
getCorrectedAutoReportingFrequency,
isPaidGroupPolicy,
isPendingDeletePolicy,
isPolicyAdmin,
Expand Down
28 changes: 26 additions & 2 deletions src/libs/actions/Policy/Policy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -343,13 +343,32 @@ function deleteWorkspace(policyID: string, policyName: string) {
function setWorkspaceAutoReportingFrequency(policyID: string, frequency: ValueOf<typeof CONST.POLICY.AUTO_REPORTING_FREQUENCIES>) {
const policy = getPolicy(policyID);

const wasPolicyOnManualReporting = PolicyUtils.getCorrectedAutoReportingFrequency(policy) === CONST.POLICY.AUTO_REPORTING_FREQUENCIES.MANUAL;

const optimisticData: OnyxUpdate[] = [
{
onyxMethod: Onyx.METHOD.MERGE,
key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`,
value: {
autoReportingFrequency: frequency,
// Recall that the "daily" and "manual" frequencies don't actually exist in Onyx or the DB (see PolicyUtils.getCorrectedAutoReportingFrequency)
autoReportingFrequency: frequency === CONST.POLICY.AUTO_REPORTING_FREQUENCIES.MANUAL ? CONST.POLICY.AUTO_REPORTING_FREQUENCIES.IMMEDIATE : frequency,
pendingFields: {autoReportingFrequency: CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE},

// To set the frequency to "manual", we really must set it to "immediate" with harvesting disabled
...(frequency === CONST.POLICY.AUTO_REPORTING_FREQUENCIES.MANUAL && {
harvesting: {
enabled: false,
},
}),

// If the policy was on manual reporting before, and now will be auto-reported,
// then we must re-enable harvesting
...(wasPolicyOnManualReporting &&
frequency !== CONST.POLICY.AUTO_REPORTING_FREQUENCIES.MANUAL && {
harvesting: {
enabled: true,
},
}),
},
},
];
Expand All @@ -360,6 +379,7 @@ function setWorkspaceAutoReportingFrequency(policyID: string, frequency: ValueOf
key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`,
value: {
autoReportingFrequency: policy?.autoReportingFrequency ?? null,
harvesting: policy?.harvesting ?? null,
pendingFields: {autoReportingFrequency: null},
errorFields: {autoReportingFrequency: ErrorUtils.getMicroSecondOnyxErrorWithTranslationKey('workflowsDelayedSubmissionPage.autoReportingFrequencyErrorMessage')},
},
Expand Down Expand Up @@ -3066,8 +3086,11 @@ function upgradeToCorporate(policyID: string, featureName: string) {
glCodes: true,
...(PolicyUtils.isInstantSubmitEnabled(policy) && {
autoReporting: true,
autoReportingFrequency: CONST.POLICY.AUTO_REPORTING_FREQUENCIES.MANUAL,
autoReportingFrequency: CONST.POLICY.AUTO_REPORTING_FREQUENCIES.IMMEDIATE,
}),
harvesting: {
enabled: false,
},
},
},
];
Expand Down Expand Up @@ -3095,6 +3118,7 @@ function upgradeToCorporate(policyID: string, featureName: string) {
glCodes: policy?.glCodes ?? null,
autoReporting: policy?.autoReporting ?? null,
autoReportingFrequency: policy?.autoReportingFrequency ?? null,
harvesting: policy?.harvesting ?? null,
},
},
];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,11 @@ const getAutoReportingFrequencyDisplayNames = (locale: Locale): AutoReportingFre
});

function WorkspaceAutoReportingFrequencyPage({policy, route}: WorkspaceAutoReportingFrequencyPageProps) {
const autoReportingFrequency = PolicyUtils.getCorrectedAutoReportingFrequency(policy);

const {translate, preferredLocale, toLocaleOrdinal} = useLocalize();
const styles = useThemeStyles();
const [isMonthlyFrequency, setIsMonthlyFrequency] = useState(policy?.autoReportingFrequency === CONST.POLICY.AUTO_REPORTING_FREQUENCIES.MONTHLY);
const [isMonthlyFrequency, setIsMonthlyFrequency] = useState(autoReportingFrequency === CONST.POLICY.AUTO_REPORTING_FREQUENCIES.MONTHLY);

const onSelectAutoReportingFrequency = (item: WorkspaceAutoReportingFrequencyPageItem) => {
Policy.setWorkspaceAutoReportingFrequency(policy?.id ?? '-1', item.keyForList as AutoReportingFrequencyKey);
Expand Down Expand Up @@ -97,16 +99,12 @@ function WorkspaceAutoReportingFrequencyPage({policy, route}: WorkspaceAutoRepor
</OfflineWithFeedback>
);

const autoReportingFrequencyItems: WorkspaceAutoReportingFrequencyPageItem[] = Object.keys(getAutoReportingFrequencyDisplayNames(preferredLocale)).map((frequencyKey) => {
const isSelected = policy?.autoReportingFrequency === frequencyKey;

return {
text: getAutoReportingFrequencyDisplayNames(preferredLocale)[frequencyKey as AutoReportingFrequencyKey] || '',
keyForList: frequencyKey,
isSelected,
footerContent: isMonthlyFrequency && frequencyKey === CONST.POLICY.AUTO_REPORTING_FREQUENCIES.MONTHLY ? monthlyFrequencyDetails() : null,
};
});
const autoReportingFrequencyItems: WorkspaceAutoReportingFrequencyPageItem[] = Object.keys(getAutoReportingFrequencyDisplayNames(preferredLocale)).map((frequencyKey) => ({
text: getAutoReportingFrequencyDisplayNames(preferredLocale)[frequencyKey as AutoReportingFrequencyKey] || '',
keyForList: frequencyKey,
isSelected: frequencyKey === autoReportingFrequency,
footerContent: isMonthlyFrequency && frequencyKey === CONST.POLICY.AUTO_REPORTING_FREQUENCIES.MONTHLY ? monthlyFrequencyDetails() : null,
}));

return (
<AccessOrNotFoundWrapper
Expand Down Expand Up @@ -138,7 +136,7 @@ function WorkspaceAutoReportingFrequencyPage({policy, route}: WorkspaceAutoRepor
ListItem={RadioListItem}
sections={[{data: autoReportingFrequencyItems}]}
onSelectRow={onSelectAutoReportingFrequency}
initiallyFocusedOptionKey={policy?.autoReportingFrequency}
initiallyFocusedOptionKey={autoReportingFrequency}
/>
</OfflineWithFeedback>
</FullPageNotFoundView>
Expand Down
4 changes: 2 additions & 2 deletions src/pages/workspace/workflows/WorkspaceWorkflowsPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ function WorkspaceWorkflowsPage({policy, betas, route}: WorkspaceWorkflowsPagePr
// Instant submit is the equivalent of delayed submissions being turned off, so we show the feature as disabled if the frequency is instant
description={
getAutoReportingFrequencyDisplayNames(preferredLocale)[
(policy?.autoReportingFrequency as AutoReportingFrequencyKey) ?? CONST.POLICY.AUTO_REPORTING_FREQUENCIES.WEEKLY
(PolicyUtils.getCorrectedAutoReportingFrequency(policy) as AutoReportingFrequencyKey) ?? CONST.POLICY.AUTO_REPORTING_FREQUENCIES.WEEKLY
]
}
shouldShowRightIcon
Expand All @@ -128,7 +128,7 @@ function WorkspaceWorkflowsPage({policy, betas, route}: WorkspaceWorkflowsPagePr
brickRoadIndicator={hasDelayedSubmissionError ? CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR : undefined}
/>
),
isActive: (policy?.harvesting?.enabled && policy.autoReportingFrequency !== CONST.POLICY.AUTO_REPORTING_FREQUENCIES.INSTANT && !hasDelayedSubmissionError) ?? false,
isActive: (policy?.autoReportingFrequency !== CONST.POLICY.AUTO_REPORTING_FREQUENCIES.INSTANT && !hasDelayedSubmissionError) ?? false,
pendingAction: policy?.pendingFields?.autoReporting,
errors: ErrorUtils.getLatestErrorField(policy ?? {}, CONST.POLICY.COLLECTION_KEYS.AUTOREPORTING),
onCloseError: () => Policy.clearPolicyErrorField(policy?.id ?? '-1', CONST.POLICY.COLLECTION_KEYS.AUTOREPORTING),
Expand Down
8 changes: 6 additions & 2 deletions src/types/onyx/Policy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1355,8 +1355,12 @@ type Policy = OnyxCommon.OnyxValueWithOfflineFeedback<
/** Whether the auto reporting is enabled */
autoReporting?: boolean;

/** The scheduled submit frequency set up on this policy */
autoReportingFrequency?: ValueOf<typeof CONST.POLICY.AUTO_REPORTING_FREQUENCIES>;
/**
* The scheduled submit frequency set up on this policy.
* Note that manual does not exist in the DB and thus should not exist in Onyx, only as a param for the API.
* "manual" really means "immediate" (aka "daily") && harvesting.enabled === false
*/
autoReportingFrequency?: Exclude<ValueOf<typeof CONST.POLICY.AUTO_REPORTING_FREQUENCIES>, typeof CONST.POLICY.AUTO_REPORTING_FREQUENCIES.MANUAL>;

/** Scheduled submit data */
harvesting?: {
Expand Down
4 changes: 2 additions & 2 deletions tests/unit/NextStepUtilsTest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -311,9 +311,9 @@ describe('libs/NextStepUtils', () => {
];

return Onyx.merge(`${ONYXKEYS.COLLECTION.POLICY}${policyID}`, {
autoReportingFrequency: CONST.POLICY.AUTO_REPORTING_FREQUENCIES.MANUAL,
autoReportingFrequency: CONST.POLICY.AUTO_REPORTING_FREQUENCIES.IMMEDIATE,
harvesting: {
enabled: true,
enabled: false,
},
}).then(() => {
const result = NextStepUtils.buildNextStep(report, CONST.REPORT.STATUS_NUM.OPEN);
Expand Down
8 changes: 7 additions & 1 deletion tests/utils/collections/policies.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import {rand, randAvatar, randBoolean, randCurrencyCode, randEmail, randPastDate, randWord} from '@ngneat/falso';
import type {ValueOf} from 'type-fest';
import CONST from '@src/CONST';
import type {Policy} from '@src/types/onyx';

Expand All @@ -9,7 +10,12 @@ export default function createRandomPolicy(index: number): Policy {
type: rand(Object.values(CONST.POLICY.TYPE)),
autoReporting: randBoolean(),
isPolicyExpenseChatEnabled: randBoolean(),
autoReportingFrequency: rand(Object.values(CONST.POLICY.AUTO_REPORTING_FREQUENCIES)),
autoReportingFrequency: rand(
Object.values(CONST.POLICY.AUTO_REPORTING_FREQUENCIES).filter(
(frequency): frequency is Exclude<ValueOf<typeof CONST.POLICY.AUTO_REPORTING_FREQUENCIES>, typeof CONST.POLICY.AUTO_REPORTING_FREQUENCIES.MANUAL> =>
frequency !== CONST.POLICY.AUTO_REPORTING_FREQUENCIES.MANUAL,
),
),
harvesting: {
enabled: randBoolean(),
},
Expand Down

0 comments on commit ebe7d58

Please sign in to comment.