Skip to content

Commit 89a2eab

Browse files
authored
[PM-23717] premium renewal email (#6672)
* [PM-23717] premium renewal email * pr feedback * pr feedback
1 parent de5a81b commit 89a2eab

6 files changed

Lines changed: 1198 additions & 8 deletions

File tree

src/Billing/Services/Implementations/UpcomingInvoiceHandler.cs

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
using Bit.Core.Entities;
1212
using Bit.Core.Models.Mail.Billing.Renewal.Families2019Renewal;
1313
using Bit.Core.Models.Mail.Billing.Renewal.Families2020Renewal;
14+
using Bit.Core.Models.Mail.Billing.Renewal.Premium;
1415
using Bit.Core.OrganizationFeatures.OrganizationSponsorships.FamiliesForEnterprise.Interfaces;
1516
using Bit.Core.Platform.Mail.Mailer;
1617
using Bit.Core.Repositories;
@@ -606,14 +607,27 @@ private async Task SendPremiumRenewalEmailAsync(
606607
User user,
607608
PremiumPlan premiumPlan)
608609
{
609-
/* TODO: Replace with proper premium renewal email template once finalized.
610-
Using Families2020RenewalMail as a temporary stop-gap. */
611-
var email = new Families2020RenewalMail
610+
var coupon = await stripeFacade.GetCoupon(CouponIDs.Milestone2SubscriptionDiscount);
611+
if (coupon == null)
612+
{
613+
throw new InvalidOperationException($"Coupon for sending premium renewal email id:{CouponIDs.Milestone2SubscriptionDiscount} not found");
614+
}
615+
616+
if (coupon.PercentOff == null)
617+
{
618+
throw new InvalidOperationException($"coupon.PercentOff for sending premium renewal email id:{CouponIDs.Milestone2SubscriptionDiscount} is null");
619+
}
620+
621+
var discountedAnnualRenewalPrice = premiumPlan.Seat.Price * (100 - coupon.PercentOff.Value) / 100;
622+
623+
var email = new PremiumRenewalMail
612624
{
613625
ToEmails = [user.Email],
614-
View = new Families2020RenewalMailView
626+
View = new PremiumRenewalMailView
615627
{
616-
MonthlyRenewalPrice = (premiumPlan.Seat.Price / 12).ToString("C", new CultureInfo("en-US"))
628+
BaseMonthlyRenewalPrice = (premiumPlan.Seat.Price / 12).ToString("C", new CultureInfo("en-US")),
629+
DiscountAmount = $"{coupon.PercentOff}%",
630+
DiscountedMonthlyRenewalPrice = (discountedAnnualRenewalPrice / 12).ToString("C", new CultureInfo("en-US"))
617631
}
618632
};
619633

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
<mjml>
2+
<mj-head>
3+
<mj-include path="../../../components/head.mjml"/>
4+
</mj-head>
5+
6+
<!-- Blue Header Section-->
7+
<mj-body css-class="border-fix">
8+
<mj-wrapper css-class="border-fix" padding="20px 20px 0px 20px">
9+
<mj-bw-simple-hero />
10+
</mj-wrapper>
11+
12+
<!-- Main Content Section -->
13+
<mj-wrapper padding="0px 20px 0px 20px">
14+
<mj-section background-color="#fff" padding="15px 10px 10px 10px">
15+
<mj-column>
16+
<mj-text font-size="16px" line-height="24px" padding="10px 15px 15px 15px">
17+
Your Bitwarden Premium subscription renews in 15 days. The price is updating to {{BaseMonthlyRenewalPrice}}/month, billed annually.
18+
</mj-text>
19+
<mj-text font-size="16px" line-height="24px" padding="10px 15px 15px 15px">
20+
As an existing Bitwarden customer, you will receive a one-time {{DiscountAmount}} loyalty discount for this renewal.
21+
This renewal now will be {{DiscountedMonthlyRenewalPrice}}/month, billed annually.
22+
</mj-text>
23+
<mj-text font-size="16px" line-height="24px" padding="10px 15px">
24+
Questions? Contact
25+
<a href="mailto:support@bitwarden.com" class="link">support@bitwarden.com</a>
26+
</mj-text>
27+
</mj-column>
28+
</mj-section>
29+
<mj-section background-color="#fff" padding="0 20px 20px 20px">
30+
</mj-section>
31+
</mj-wrapper>
32+
33+
<!-- Learn More Section -->
34+
<mj-wrapper padding="0px 20px 10px 20px">
35+
<mj-bw-learn-more-footer/>
36+
</mj-wrapper>
37+
38+
<!-- Footer -->
39+
<mj-include path="../../../components/footer.mjml"/>
40+
</mj-body>
41+
</mjml>
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
using Bit.Core.Platform.Mail.Mailer;
2+
3+
namespace Bit.Core.Models.Mail.Billing.Renewal.Premium;
4+
5+
public class PremiumRenewalMailView : BaseMailView
6+
{
7+
public required string BaseMonthlyRenewalPrice { get; set; }
8+
public required string DiscountedMonthlyRenewalPrice { get; set; }
9+
public required string DiscountAmount { get; set; }
10+
}
11+
12+
public class PremiumRenewalMail : BaseMail<PremiumRenewalMailView>
13+
{
14+
public override string Subject { get => "Your Bitwarden Premium renewal is updating"; }
15+
}

0 commit comments

Comments
 (0)