Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 8 additions & 9 deletions src/libs/SubscriptionUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@
};

let currentUserAccountID = -1;
Onyx.connect({

Check warning on line 54 in src/libs/SubscriptionUtils.ts

View workflow job for this annotation

GitHub Actions / Changed files ESLint check

Onyx.connect() is deprecated. Use useOnyx() hook instead and pass the data as parameters to a pure function
key: ONYXKEYS.SESSION,
callback: (value) => {
currentUserAccountID = value?.accountID ?? CONST.DEFAULT_NUMBER_ID;
Expand All @@ -59,25 +59,25 @@
});

let amountOwed: OnyxEntry<number>;
Onyx.connect({

Check warning on line 62 in src/libs/SubscriptionUtils.ts

View workflow job for this annotation

GitHub Actions / Changed files ESLint check

Onyx.connect() is deprecated. Use useOnyx() hook instead and pass the data as parameters to a pure function
key: ONYXKEYS.NVP_PRIVATE_AMOUNT_OWED,
callback: (value) => (amountOwed = value),
});

let billingStatus: OnyxEntry<BillingStatus>;
Onyx.connect({

Check warning on line 68 in src/libs/SubscriptionUtils.ts

View workflow job for this annotation

GitHub Actions / Changed files ESLint check

Onyx.connect() is deprecated. Use useOnyx() hook instead and pass the data as parameters to a pure function
key: ONYXKEYS.NVP_PRIVATE_BILLING_STATUS,
callback: (value) => (billingStatus = value),
});

let ownerBillingGraceEndPeriod: OnyxEntry<number>;
Onyx.connect({

Check warning on line 74 in src/libs/SubscriptionUtils.ts

View workflow job for this annotation

GitHub Actions / Changed files ESLint check

Onyx.connect() is deprecated. Use useOnyx() hook instead and pass the data as parameters to a pure function
key: ONYXKEYS.NVP_PRIVATE_OWNER_BILLING_GRACE_PERIOD_END,
callback: (value) => (ownerBillingGraceEndPeriod = value),
});

let fundList: OnyxEntry<FundList>;
Onyx.connect({

Check warning on line 80 in src/libs/SubscriptionUtils.ts

View workflow job for this annotation

GitHub Actions / Changed files ESLint check

Onyx.connect() is deprecated. Use useOnyx() hook instead and pass the data as parameters to a pure function
key: ONYXKEYS.FUND_LIST,
callback: (value) => {
if (!value) {
Expand All @@ -89,7 +89,7 @@
});

let retryBillingFailed: OnyxEntry<boolean>;
Onyx.connect({

Check warning on line 92 in src/libs/SubscriptionUtils.ts

View workflow job for this annotation

GitHub Actions / Changed files ESLint check

Onyx.connect() is deprecated. Use useOnyx() hook instead and pass the data as parameters to a pure function
key: ONYXKEYS.SUBSCRIPTION_RETRY_BILLING_STATUS_FAILED,
callback: (value) => {
if (value === undefined) {
Expand All @@ -102,26 +102,20 @@
});

let lastDayFreeTrial: OnyxEntry<string>;
Onyx.connect({

Check warning on line 105 in src/libs/SubscriptionUtils.ts

View workflow job for this annotation

GitHub Actions / Changed files ESLint check

Onyx.connect() is deprecated. Use useOnyx() hook instead and pass the data as parameters to a pure function
key: ONYXKEYS.NVP_LAST_DAY_FREE_TRIAL,
callback: (value) => (lastDayFreeTrial = value),
});

let userBillingFundID: OnyxEntry<number>;
Onyx.connect({
key: ONYXKEYS.NVP_BILLING_FUND_ID,
callback: (value) => (userBillingFundID = value),
});

let userBillingGraceEndPeriodCollection: OnyxCollection<BillingGraceEndPeriod>;
Onyx.connect({

Check warning on line 111 in src/libs/SubscriptionUtils.ts

View workflow job for this annotation

GitHub Actions / Changed files ESLint check

Onyx.connect() is deprecated. Use useOnyx() hook instead and pass the data as parameters to a pure function
key: ONYXKEYS.COLLECTION.SHARED_NVP_PRIVATE_USER_BILLING_GRACE_PERIOD_END,
callback: (value) => (userBillingGraceEndPeriodCollection = value),
waitForCollectionCallback: true,
});

let allPolicies: OnyxCollection<Policy>;
Onyx.connect({

Check warning on line 118 in src/libs/SubscriptionUtils.ts

View workflow job for this annotation

GitHub Actions / Changed files ESLint check

Onyx.connect() is deprecated. Use useOnyx() hook instead and pass the data as parameters to a pure function
key: ONYXKEYS.COLLECTION.POLICY,
callback: (value) => (allPolicies = value),
waitForCollectionCallback: true,
Expand Down Expand Up @@ -229,7 +223,12 @@
return isExpiringThisMonth || isExpiringNextMonth;
}

function shouldShowDiscountBanner(hasTeam2025Pricing: boolean, subscriptionPlan: ValueOf<typeof CONST.POLICY.TYPE> | null, firstDayFreeTrial: string | undefined): boolean {
function shouldShowDiscountBanner(
hasTeam2025Pricing: boolean,
subscriptionPlan: ValueOf<typeof CONST.POLICY.TYPE> | null,
firstDayFreeTrial: string | undefined,
userBillingFundID: number | undefined,
): boolean {
if (!getOwnedPaidPolicies(allPolicies, currentUserAccountID)?.length) {
return false;
}
Expand All @@ -238,7 +237,7 @@
return false;
}

if (doesUserHavePaymentCardAdded()) {
if (doesUserHavePaymentCardAdded(userBillingFundID)) {
return false;
}

Expand Down Expand Up @@ -490,7 +489,7 @@
/**
* Whether the user has a payment card added to its account.
*/
function doesUserHavePaymentCardAdded(): boolean {
function doesUserHavePaymentCardAdded(userBillingFundID: number | undefined): boolean {
return userBillingFundID !== undefined;
}

Expand Down
5 changes: 3 additions & 2 deletions src/pages/home/HeaderView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ function HeaderView({report, parentReportAction, onNavigationMenuButtonClicked,
const [grandParentReportActions] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${getNonEmptyStringOnyxID(parentReport?.parentReportID)}`, {canBeMissing: true});
const policy = usePolicy(report?.policyID);
const [personalDetails] = useOnyx(ONYXKEYS.PERSONAL_DETAILS_LIST, {canBeMissing: true});
const [userBillingFundID] = useOnyx(ONYXKEYS.NVP_BILLING_FUND_ID, {canBeMissing: true});
const shouldShowLoadingBar = useLoadingBarVisibility();
const [firstDayFreeTrial] = useOnyx(ONYXKEYS.NVP_FIRST_DAY_FREE_TRIAL, {canBeMissing: true});
const [lastDayFreeTrial] = useOnyx(ONYXKEYS.NVP_LAST_DAY_FREE_TRIAL, {canBeMissing: true});
Expand Down Expand Up @@ -205,10 +206,10 @@ function HeaderView({report, parentReportAction, onNavigationMenuButtonClicked,
// If the onboarding report is directly loaded, shouldShowDiscountBanner can return wrong value as it is not
// linked to the react lifecycle directly. Wait for trial dates to load, before calculating.
const shouldShowDiscount = useMemo(
() => shouldShowDiscountBanner(hasTeam2025Pricing, subscriptionPlan, firstDayFreeTrial) && !isReportArchived,
() => shouldShowDiscountBanner(hasTeam2025Pricing, subscriptionPlan, firstDayFreeTrial, userBillingFundID) && !isReportArchived,
// eslint-disable-next-line react-compiler/react-compiler
// eslint-disable-next-line react-hooks/exhaustive-deps
[firstDayFreeTrial, lastDayFreeTrial, hasTeam2025Pricing, reportNameValuePairs, subscriptionPlan],
[firstDayFreeTrial, lastDayFreeTrial, hasTeam2025Pricing, reportNameValuePairs, subscriptionPlan, userBillingFundID],
);

const shouldShowSubscript = shouldReportShowSubscript(report, isReportArchived);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
import React from 'react';
import * as Illustrations from '@components/Icon/Illustrations';
import useLocalize from '@hooks/useLocalize';
import * as SubscriptionUtils from '@libs/SubscriptionUtils';
import useOnyx from '@hooks/useOnyx';
import {doesUserHavePaymentCardAdded} from '@libs/SubscriptionUtils';
import ONYXKEYS from '@src/ONYXKEYS';
import BillingBanner from './BillingBanner';

function TrialEndedBillingBanner() {
const {translate} = useLocalize();
const [userBillingFundID] = useOnyx(ONYXKEYS.NVP_BILLING_FUND_ID, {canBeMissing: true});

if (SubscriptionUtils.doesUserHavePaymentCardAdded()) {
if (doesUserHavePaymentCardAdded(userBillingFundID)) {
return null;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,20 @@
import React from 'react';
import * as Illustrations from '@components/Icon/Illustrations';
import useLocalize from '@hooks/useLocalize';
import * as SubscriptionUtils from '@libs/SubscriptionUtils';
import useOnyx from '@hooks/useOnyx';
import {calculateRemainingFreeTrialDays, doesUserHavePaymentCardAdded} from '@libs/SubscriptionUtils';
import ONYXKEYS from '@src/ONYXKEYS';
import BillingBanner from './BillingBanner';

function TrialStartedBillingBanner() {
const {translate} = useLocalize();
const [userBillingFundID] = useOnyx(ONYXKEYS.NVP_BILLING_FUND_ID, {canBeMissing: true});

const subtitle = !SubscriptionUtils.doesUserHavePaymentCardAdded() ? translate('subscription.billingBanner.trialStarted.subtitle') : '';
const subtitle = !doesUserHavePaymentCardAdded(userBillingFundID) ? translate('subscription.billingBanner.trialStarted.subtitle') : '';

return (
<BillingBanner
title={translate('subscription.billingBanner.trialStarted.title', {numOfDays: SubscriptionUtils.calculateRemainingFreeTrialDays()})}
title={translate('subscription.billingBanner.trialStarted.title', {numOfDays: calculateRemainingFreeTrialDays()})}
subtitle={subtitle}
icon={Illustrations.TreasureChest}
/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ function CardSection() {
);
const [firstDayFreeTrial] = useOnyx(ONYXKEYS.NVP_FIRST_DAY_FREE_TRIAL, {canBeMissing: true});
const [billingDisputePending] = useOnyx(ONYXKEYS.NVP_PRIVATE_BILLING_DISPUTE_PENDING, {canBeMissing: true});
const [userBillingFundID] = useOnyx(ONYXKEYS.NVP_BILLING_FUND_ID, {canBeMissing: true});
const requestRefund = useCallback(() => {
requestRefundByUser();
setIsRequestRefundModalVisible(false);
Expand Down Expand Up @@ -139,7 +140,7 @@ function CardSection() {
};

let BillingBanner: React.ReactNode | undefined;
if (shouldShowDiscountBanner(hasTeam2025Pricing, subscriptionPlan, firstDayFreeTrial)) {
if (shouldShowDiscountBanner(hasTeam2025Pricing, subscriptionPlan, firstDayFreeTrial, userBillingFundID)) {
BillingBanner = <EarlyDiscountBanner isSubscriptionPage />;
} else if (shouldShowPreTrialBillingBanner(introSelected, firstDayFreeTrial)) {
BillingBanner = <PreTrialBillingBanner />;
Expand Down
14 changes: 7 additions & 7 deletions tests/unit/SubscriptionUtilsTest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -183,12 +183,12 @@ describe('SubscriptionUtils', () => {
});

it('should return false if the Onyx key is not set', () => {
expect(doesUserHavePaymentCardAdded()).toBeFalsy();
expect(doesUserHavePaymentCardAdded(undefined)).toBeFalsy();
});

it('should return true if the Onyx key is set', async () => {
await Onyx.set(ONYXKEYS.NVP_BILLING_FUND_ID, 8010);
expect(doesUserHavePaymentCardAdded()).toBeTruthy();
expect(doesUserHavePaymentCardAdded(8010)).toBeTruthy();
});
});

Expand Down Expand Up @@ -529,7 +529,7 @@ describe('SubscriptionUtils', () => {
[ONYXKEYS.NVP_FIRST_DAY_FREE_TRIAL]: null,
[ONYXKEYS.NVP_LAST_DAY_FREE_TRIAL]: null,
});
expect(shouldShowDiscountBanner(true, 'corporate', undefined)).toBeFalsy();
expect(shouldShowDiscountBanner(true, 'corporate', undefined, undefined)).toBeFalsy();
});

it(`should return false if user has already added a payment method`, async () => {
Expand All @@ -542,7 +542,7 @@ describe('SubscriptionUtils', () => {
},
[ONYXKEYS.NVP_BILLING_FUND_ID]: 8010,
});
expect(shouldShowDiscountBanner(true, 'corporate', undefined)).toBeFalsy();
expect(shouldShowDiscountBanner(true, 'corporate', undefined, 8010)).toBeFalsy();
});

it('should return false if the user is on Team plan', async () => {
Expand All @@ -557,7 +557,7 @@ describe('SubscriptionUtils', () => {
[ONYXKEYS.NVP_FIRST_DAY_FREE_TRIAL]: firstDayFreeTrial,
[ONYXKEYS.NVP_LAST_DAY_FREE_TRIAL]: formatDate(addDays(new Date(), 10), CONST.DATE.FNS_DATE_TIME_FORMAT_STRING),
});
expect(shouldShowDiscountBanner(true, 'team', firstDayFreeTrial)).toBeFalsy();
expect(shouldShowDiscountBanner(true, 'team', firstDayFreeTrial, undefined)).toBeFalsy();
});

it('should return true if the date is before the free trial end date or within the 8 days from the trial start date', async () => {
Expand All @@ -572,7 +572,7 @@ describe('SubscriptionUtils', () => {
[ONYXKEYS.NVP_FIRST_DAY_FREE_TRIAL]: firstDayFreeTrial,
[ONYXKEYS.NVP_LAST_DAY_FREE_TRIAL]: formatDate(addDays(new Date(), 10), CONST.DATE.FNS_DATE_TIME_FORMAT_STRING),
});
expect(shouldShowDiscountBanner(true, 'corporate', firstDayFreeTrial)).toBeTruthy();
expect(shouldShowDiscountBanner(true, 'corporate', firstDayFreeTrial, undefined)).toBeTruthy();
});

it("should return false if user's trial is during the discount period but has no workspaces", async () => {
Expand All @@ -582,7 +582,7 @@ describe('SubscriptionUtils', () => {
[ONYXKEYS.NVP_FIRST_DAY_FREE_TRIAL]: firstDayFreeTrial,
[ONYXKEYS.NVP_LAST_DAY_FREE_TRIAL]: formatDate(addDays(new Date(), 10), CONST.DATE.FNS_DATE_TIME_FORMAT_STRING),
});
expect(shouldShowDiscountBanner(true, 'corporate', firstDayFreeTrial)).toBeFalsy();
expect(shouldShowDiscountBanner(true, 'corporate', firstDayFreeTrial, undefined)).toBeFalsy();
});
});

Expand Down
Loading