diff --git a/server/channels/api4/cloud.go b/server/channels/api4/cloud.go
index fc1c6ce33a..1c448a0efd 100644
--- a/server/channels/api4/cloud.go
+++ b/server/channels/api4/cloud.go
@@ -103,6 +103,7 @@ func getSubscription(c *Context, w http.ResponseWriter, r *http.Request) {
DNS: "",
LastInvoice: &model.Invoice{},
DelinquentSince: subscription.DelinquentSince,
+ BillingType: "",
}
}
diff --git a/server/model/cloud.go b/server/model/cloud.go
index a2176f8bd9..1efad1878c 100644
--- a/server/model/cloud.go
+++ b/server/model/cloud.go
@@ -179,6 +179,7 @@ type Subscription struct {
DelinquentSince *int64 `json:"delinquent_since"`
OriginallyLicensedSeats int `json:"originally_licensed_seats"`
ComplianceBlocked string `json:"compliance_blocked"`
+ BillingType string `json:"billing_type"`
}
// Subscription History model represents true up event in a yearly subscription
diff --git a/webapp/channels/src/components/admin_console/billing/billing_subscriptions/to_yearly_nudge_banner.test.tsx b/webapp/channels/src/components/admin_console/billing/billing_subscriptions/to_yearly_nudge_banner.test.tsx
index e9061333a5..1fd7456656 100644
--- a/webapp/channels/src/components/admin_console/billing/billing_subscriptions/to_yearly_nudge_banner.test.tsx
+++ b/webapp/channels/src/components/admin_console/billing/billing_subscriptions/to_yearly_nudge_banner.test.tsx
@@ -197,6 +197,58 @@ describe('ToYearlyNudgeBannerDismissable', () => {
expect(() => screen.getByTestId('cloud-pro-monthly-deprecation-announcement-bar')).toThrow();
});
+
+ test('should NOT show when subscription has billing type of internal', () => {
+ const state = JSON.parse(JSON.stringify(initialState));
+ state.entities.users.profiles = {
+ current_user_id: {roles: 'system_admin'},
+ };
+ state.entities.cloud = {
+ subscription: {
+ product_id: 'prod_professional',
+ is_free_trial: 'false',
+ trial_end_at: 1,
+ billing_type: 'internal',
+ },
+ products: {
+ prod_professional: {
+ id: 'prod_professional',
+ sku: CloudProducts.PROFESSIONAL,
+ recurring_interval: RecurringIntervals.MONTH,
+ },
+ },
+ };
+
+ renderWithIntlAndStore(, state);
+
+ expect(() => screen.getByTestId('cloud-pro-monthly-deprecation-announcement-bar')).toThrow();
+ });
+
+ test('should NOT show when subscription has billing type of licensed', () => {
+ const state = JSON.parse(JSON.stringify(initialState));
+ state.entities.users.profiles = {
+ current_user_id: {roles: 'system_admin'},
+ };
+ state.entities.cloud = {
+ subscription: {
+ product_id: 'prod_professional',
+ is_free_trial: 'false',
+ trial_end_at: 1,
+ billing_type: 'licensed',
+ },
+ products: {
+ prod_professional: {
+ id: 'prod_professional',
+ sku: CloudProducts.PROFESSIONAL,
+ recurring_interval: RecurringIntervals.MONTH,
+ },
+ },
+ };
+
+ renderWithIntlAndStore(, state);
+
+ expect(() => screen.getByTestId('cloud-pro-monthly-deprecation-announcement-bar')).toThrow();
+ });
});
describe('ToYearlyNudgeBanner', () => {
@@ -241,6 +293,51 @@ describe('ToYearlyNudgeBanner', () => {
renderWithIntlAndStore(, state);
+ expect(() => screen.getByTestId('cloud-pro-monthly-deprecation-alert-banner')).toThrow();
+ });
+ test('should NOT show when subscription has billing type of internal', () => {
+ const state = JSON.parse(JSON.stringify(initialState));
+ state.entities.cloud = {
+ subscription: {
+ product_id: 'prod_professional',
+ is_free_trial: 'false',
+ trial_end_at: 1,
+ billing_type: 'internal',
+ },
+ products: {
+ prod_professional: {
+ id: 'prod_professional',
+ sku: CloudProducts.PROFESSIONAL,
+ recurring_interval: RecurringIntervals.MONTH,
+ },
+ },
+ };
+
+ renderWithIntlAndStore(, state);
+
+ expect(() => screen.getByTestId('cloud-pro-monthly-deprecation-alert-banner')).toThrow();
+ });
+
+ test('should NOT show when subscription has billing type of licensed', () => {
+ const state = JSON.parse(JSON.stringify(initialState));
+ state.entities.cloud = {
+ subscription: {
+ product_id: 'prod_professional',
+ is_free_trial: 'false',
+ trial_end_at: 1,
+ billing_type: 'licensed',
+ },
+ products: {
+ prod_professional: {
+ id: 'prod_professional',
+ sku: CloudProducts.PROFESSIONAL,
+ recurring_interval: RecurringIntervals.MONTH,
+ },
+ },
+ };
+
+ renderWithIntlAndStore(, state);
+
expect(() => screen.getByTestId('cloud-pro-monthly-deprecation-alert-banner')).toThrow();
});
});
diff --git a/webapp/channels/src/components/admin_console/billing/billing_subscriptions/to_yearly_nudge_banner.tsx b/webapp/channels/src/components/admin_console/billing/billing_subscriptions/to_yearly_nudge_banner.tsx
index f2eac86e69..e5640663b0 100644
--- a/webapp/channels/src/components/admin_console/billing/billing_subscriptions/to_yearly_nudge_banner.tsx
+++ b/webapp/channels/src/components/admin_console/billing/billing_subscriptions/to_yearly_nudge_banner.tsx
@@ -11,12 +11,12 @@ import useOpenCloudPurchaseModal from 'components/common/hooks/useOpenCloudPurch
import useOpenSalesLink from 'components/common/hooks/useOpenSalesLink';
import AnnouncementBar from 'components/announcement_bar/default_announcement_bar';
-import {getSubscriptionProduct as selectSubscriptionProduct} from 'mattermost-redux/selectors/entities/cloud';
+import {getSubscriptionProduct as selectSubscriptionProduct, getCloudSubscription as selectCloudSubscription} from 'mattermost-redux/selectors/entities/cloud';
import {getCurrentUser, isCurrentUserSystemAdmin} from 'mattermost-redux/selectors/entities/users';
import {savePreferences} from 'mattermost-redux/actions/preferences';
import {get as getPreference} from 'mattermost-redux/selectors/entities/preferences';
-import {AnnouncementBarTypes, CloudBanners, CloudProducts, Preferences, RecurringIntervals} from 'utils/constants';
+import {AnnouncementBarTypes, CloudBanners, CloudProducts, Preferences, RecurringIntervals, CloudBillingTypes} from 'utils/constants';
import {t} from 'utils/i18n';
import {GlobalState} from '@mattermost/types/store';
@@ -53,6 +53,7 @@ const ToYearlyNudgeBannerDismissable = () => {
const show = snoozeInfo.show;
const currentUser = useSelector(getCurrentUser);
+ const subscription = useSelector(selectCloudSubscription);
const isAdmin = useSelector(isCurrentUserSystemAdmin);
const product = useSelector(selectSubscriptionProduct);
const currentProductProfessional = product?.sku === CloudProducts.PROFESSIONAL;
@@ -139,6 +140,10 @@ const ToYearlyNudgeBannerDismissable = () => {
return null;
}
+ if (subscription?.billing_type === CloudBillingTypes.INTERNAL || subscription?.billing_type === CloudBillingTypes.LICENSED) {
+ return null;
+ }
+
const message = (
{
showCloseButton={daysToProMonthlyEnd > 10}
onButtonClick={() => openPurchaseModal({trackingLocation: 'to_yearly_nudge_annoucement_bar'})}
modalButtonText={t('cloud_billing.nudge_to_yearly.learn_more')}
- modalButtonDefaultText='Learn more'
+ modalButtonDefaultText='Update billing'
message={message}
showLinkAsButton={true}
handleClose={showBanner}
@@ -173,6 +178,7 @@ const ToYearlyNudgeBanner = () => {
const [openSalesLink] = useOpenSalesLink();
const openPurchaseModal = useOpenCloudPurchaseModal({});
+ const subscription = useSelector(selectCloudSubscription);
const product = useSelector(selectSubscriptionProduct);
const currentProductProfessional = product?.sku === CloudProducts.PROFESSIONAL;
const currentProductIsMonthly = product?.recurring_interval === RecurringIntervals.MONTH;
@@ -182,6 +188,10 @@ const ToYearlyNudgeBanner = () => {
return null;
}
+ if (subscription?.billing_type === CloudBillingTypes.INTERNAL || subscription?.billing_type === CloudBillingTypes.LICENSED) {
+ return null;
+ }
+
const now = moment(Date.now());
const proMonthlyEndDate = moment(cloudProMonthlyCloseMoment, 'YYYYMMDD');
const daysToProMonthlyEnd = proMonthlyEndDate.diff(now, 'days');
diff --git a/webapp/channels/src/i18n/en.json b/webapp/channels/src/i18n/en.json
index c5af857223..4d1aee8c3f 100644
--- a/webapp/channels/src/i18n/en.json
+++ b/webapp/channels/src/i18n/en.json
@@ -3056,7 +3056,7 @@
"cloud_billing.nudge_to_yearly.announcement_bar": "Monthly billing will be discontinued in {days} days . Switch to annual billing",
"cloud_billing.nudge_to_yearly.contact_sales": "Contact sales",
"cloud_billing.nudge_to_yearly.description": "Monthly billing will be discontinued on {date}. To keep your workspace, switch to annual billing.",
- "cloud_billing.nudge_to_yearly.learn_more": "Learn more",
+ "cloud_billing.nudge_to_yearly.learn_more": "Update billing",
"cloud_billing.nudge_to_yearly.title": "Action required: Switch to annual billing to keep your workspace.",
"cloud_delinquency.banner.buttonText": "Update billing now",
"cloud_delinquency.banner.end_user_notify_admin_button": "Notify admin",
diff --git a/webapp/channels/src/utils/constants.tsx b/webapp/channels/src/utils/constants.tsx
index 7f1dce9244..91b82df939 100644
--- a/webapp/channels/src/utils/constants.tsx
+++ b/webapp/channels/src/utils/constants.tsx
@@ -504,6 +504,11 @@ export const CloudProducts = {
LEGACY: 'cloud-legacy',
};
+export const CloudBillingTypes = {
+ INTERNAL: 'internal',
+ LICENSED: 'licensed',
+};
+
export const SelfHostedProducts = {
STARTER: 'starter',
PROFESSIONAL: 'professional',
diff --git a/webapp/platform/types/src/cloud.ts b/webapp/platform/types/src/cloud.ts
index 74b7195ab2..9cdb28a01c 100644
--- a/webapp/platform/types/src/cloud.ts
+++ b/webapp/platform/types/src/cloud.ts
@@ -41,6 +41,7 @@ export type Subscription = {
is_free_trial: string;
delinquent_since?: number;
compliance_blocked?: string;
+ billing_type?: string;
}
export type Product = {