From 7039176d312497e1d2912227806801f65e896a12 Mon Sep 17 00:00:00 2001 From: Nick Misasi Date: Tue, 16 Jan 2024 17:48:59 -0500 Subject: [PATCH] [CLD-6536] Adjustments to cloud annual renewal announcement bar (#25927) * Adjustments to cloud annual renewal announcement bar * Add exclusion for trials * Add more exceptions for when on trial during renewal period * Add support for simulated_current_time_ms * A few more changes to allow us to test this post-merge * Fix tests, pipeline * Final fix around emails --------- Co-authored-by: Mattermost Build --- server/channels/api4/cloud.go | 4 ++++ server/channels/app/cloud.go | 10 ++++++--- server/public/model/cloud.go | 13 +++++------- .../billing_subscriptions.tsx | 11 +++++++--- .../cloud_annual_renewal/index.tsx | 10 ++++++--- .../src/components/purchase_modal/index.ts | 2 +- webapp/channels/src/utils/cloud_utils.ts | 21 +++++++++++++++---- webapp/platform/types/src/cloud.ts | 1 + 8 files changed, 50 insertions(+), 22 deletions(-) diff --git a/server/channels/api4/cloud.go b/server/channels/api4/cloud.go index 58b06dc9c2..08085ca4ab 100644 --- a/server/channels/api4/cloud.go +++ b/server/channels/api4/cloud.go @@ -111,6 +111,10 @@ func getSubscription(c *Context, w http.ResponseWriter, r *http.Request) { } } + if model.GetServiceEnvironment() != model.ServiceEnvironmentTest { + subscription.SimulatedCurrentTimeMs = nil + } + if !c.App.Config().FeatureFlags.CloudAnnualRenewals { subscription.WillRenew = "" subscription.CancelAt = nil diff --git a/server/channels/app/cloud.go b/server/channels/app/cloud.go index 2f8909b8f0..788c5eae7a 100644 --- a/server/channels/app/cloud.go +++ b/server/channels/app/cloud.go @@ -285,6 +285,10 @@ func (a *App) DoSubscriptionRenewalCheck() { return } + if subscription.IsFreeTrial == "true" { + return // Don't send renewal emails for free trials + } + sysVar, err := a.Srv().Store().System().GetByName(model.CloudRenewalEmail) if err != nil { // We only care about the error if it wasn't a not found error @@ -318,13 +322,13 @@ func (a *App) DoSubscriptionRenewalCheck() { // Only send the email if within the period and it's not already been sent // This allows the email to send on day 59 if for whatever reason it was unable to on day 60 - if daysToExpiration <= 60 && daysToExpiration > 30 && prevSentEmail != 60 { + if daysToExpiration <= 60 && daysToExpiration > 30 && prevSentEmail != 60 && !(prevSentEmail < 60) { emailFunc = a.Srv().EmailService.SendCloudRenewalEmail60 prevSentEmail = 60 - } else if daysToExpiration <= 30 && daysToExpiration > 7 && prevSentEmail != 30 { + } else if daysToExpiration <= 30 && daysToExpiration > 7 && prevSentEmail != 30 && !(prevSentEmail < 30) { emailFunc = a.Srv().EmailService.SendCloudRenewalEmail30 prevSentEmail = 30 - } else if daysToExpiration <= 7 && daysToExpiration > 3 && prevSentEmail != 7 { + } else if daysToExpiration <= 7 && daysToExpiration >= 0 && prevSentEmail != 7 { emailFunc = a.Srv().EmailService.SendCloudRenewalEmail7 prevSentEmail = 7 } diff --git a/server/public/model/cloud.go b/server/public/model/cloud.go index 3dba37d279..fd62eca4dd 100644 --- a/server/public/model/cloud.go +++ b/server/public/model/cloud.go @@ -5,8 +5,6 @@ package model import ( "encoding/json" - "os" - "strconv" "strings" "time" ) @@ -185,17 +183,16 @@ type Subscription struct { BillingType string `json:"billing_type"` CancelAt *int64 `json:"cancel_at"` WillRenew string `json:"will_renew"` + SimulatedCurrentTimeMs *int64 `json:"simulated_current_time_ms"` } func (s *Subscription) DaysToExpiration() int64 { now := time.Now().UnixMilli() - // Allows us to base the current time off of an environment variable for testing purposes if GetServiceEnvironment() == ServiceEnvironmentTest { - if currTime, set := os.LookupEnv("CLOUD_MOCK_CURRENT_TIME"); set { - timeInt, err := strconv.ParseInt(currTime, 10, 64) - if err == nil { - now = time.Unix(timeInt, 0).UnixMilli() - } + // In the test environment we have test clocks. A test clock is a ms timestamp + // If it's not nil, we use it as the current time in all calculations + if s.SimulatedCurrentTimeMs != nil { + now = *s.SimulatedCurrentTimeMs } } daysToExpiry := (s.EndAt - now) / (1000 * 60 * 60 * 24) diff --git a/webapp/channels/src/components/admin_console/billing/billing_subscriptions/billing_subscriptions.tsx b/webapp/channels/src/components/admin_console/billing/billing_subscriptions/billing_subscriptions.tsx index 7ab34a775b..b734730963 100644 --- a/webapp/channels/src/components/admin_console/billing/billing_subscriptions/billing_subscriptions.tsx +++ b/webapp/channels/src/components/admin_console/billing/billing_subscriptions/billing_subscriptions.tsx @@ -11,7 +11,7 @@ import useGetSubscription from 'components/common/hooks/useGetSubscription'; import useOpenCloudPurchaseModal from 'components/common/hooks/useOpenCloudPurchaseModal'; import useOpenSalesLink from 'components/common/hooks/useOpenSalesLink'; -import {daysToExpiration} from 'utils/cloud_utils'; +import {daysToCancellation, daysToExpiration} from 'utils/cloud_utils'; export const creditCardExpiredBanner = (setShowCreditCardBanner: (value: boolean) => void) => { return ( @@ -68,8 +68,8 @@ export const CloudAnnualRenewalBanner = () => { if (!subscription || !subscription.cancel_at || (subscription.will_renew === 'true' && !subscription.delinquent_since)) { return null; } - const daysUntilExpiration = daysToExpiration(subscription?.end_at); - const daysUntilCancelation = daysToExpiration(subscription?.cancel_at); + const daysUntilExpiration = daysToExpiration(subscription); + const daysUntilCancelation = daysToCancellation(subscription); const renewButton = (