Browse Source

Add Premium end date reminder worker

pull/69/head
Berkan Sasmaz 5 years ago
parent
commit
7a82e6d77a
  1. 3
      src/EventHub.BackgroundServices/EventHubBackgroundServicesModule.cs
  2. 59
      src/EventHub.BackgroundServices/Organizations/OrganizationPremiumEndDateNotifier.cs
  3. 99
      src/EventHub.BackgroundServices/Organizations/OrganizationPremiumEndDateWorker.cs
  4. 9
      src/EventHub.Domain/Emailing/EmailTemplateDefinitionProvider.cs
  5. 2
      src/EventHub.Domain/Emailing/EmailTemplates.cs
  6. 334
      src/EventHub.Domain/Emailing/Templates/PremiumEndDateReminder.tpl
  7. 9
      src/EventHub.Domain/Organizations/Organization.cs
  8. 2707
      src/EventHub.EntityFrameworkCore/Migrations/20211027131803_Added_IsSendPremiumReminderEmail_To_Organization.Designer.cs
  9. 26
      src/EventHub.EntityFrameworkCore/Migrations/20211027131803_Added_IsSendPremiumReminderEmail_To_Organization.cs
  10. 3
      src/EventHub.EntityFrameworkCore/Migrations/EventHubDbContextModelSnapshot.cs
  11. 2
      src/EventHub.Web/Pages/Pricing.cshtml
  12. 12
      src/EventHub.Web/Pages/Pricing.cshtml.cs

3
src/EventHub.BackgroundServices/EventHubBackgroundServicesModule.cs

@ -1,5 +1,6 @@
using EventHub.EntityFrameworkCore;
using EventHub.Events;
using EventHub.Organizations;
using Microsoft.AspNetCore.DataProtection;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
@ -45,6 +46,8 @@ namespace EventHub
context.AddBackgroundWorker<EventReminderWorker>();
context.AddBackgroundWorker<NewEventWorker>();
context.AddBackgroundWorker<EventTimingChangeWorker>();
context.AddBackgroundWorker<OrganizationPremiumEndDateWorker>();
}
}
}

59
src/EventHub.BackgroundServices/Organizations/OrganizationPremiumEndDateNotifier.cs

@ -0,0 +1,59 @@
using System;
using System.Threading.Tasks;
using EventHub.Emailing;
using Microsoft.Extensions.Logging;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Domain.Repositories;
using Volo.Abp.Emailing;
using Volo.Abp.Identity;
using Volo.Abp.TextTemplating;
namespace EventHub.Organizations
{
public class OrganizationPremiumEndDateNotifier : ITransientDependency
{
private readonly IEmailSender _emailSender;
private readonly ITemplateRenderer _templateRenderer;
private readonly IRepository<IdentityUser, Guid> _userRepository;
private readonly ILogger<OrganizationPremiumEndDateNotifier> _logger;
public OrganizationPremiumEndDateNotifier(
IEmailSender emailSender,
ITemplateRenderer templateRenderer,
IRepository<IdentityUser, Guid> userRepository,
ILogger<OrganizationPremiumEndDateNotifier> logger)
{
_emailSender = emailSender;
_templateRenderer = templateRenderer;
_userRepository = userRepository;
_logger = logger;
}
public async Task NotifyAsync(Organization organization)
{
if (organization is null || organization.IsSendPremiumReminderEmail || !organization.IsPremium)
{
return;
}
var user = await _userRepository.FindAsync(organization.OwnerUserId);
if (user is null)
{
_logger.LogError("(OrganizationPremiumEndDateNotifier) User not found!");
return;
}
var templateModel = new
{
OrganizationName = organization.Name,
EndDate = organization.PremiumEndDate!.Value.ToShortDateString()
};
await _emailSender.SendAsync(
user.Email,
"EventHub: Your Premium Organization is expiring!",
await _templateRenderer.RenderAsync(EmailTemplates.PremiumEndDateReminder, templateModel)
);
}
}
}

99
src/EventHub.BackgroundServices/Organizations/OrganizationPremiumEndDateWorker.cs

@ -0,0 +1,99 @@
using System;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Volo.Abp.BackgroundWorkers;
using Volo.Abp.Domain.Repositories;
using Volo.Abp.Linq;
using Volo.Abp.Threading;
using Volo.Abp.Timing;
using Volo.Abp.Uow;
namespace EventHub.Organizations
{
public class OrganizationPremiumEndDateWorker : AsyncPeriodicBackgroundWorkerBase
{
public OrganizationPremiumEndDateWorker(AbpAsyncTimer timer, IServiceScopeFactory serviceScopeFactory) : base(timer, serviceScopeFactory)
{
Timer.Period = (int)TimeSpan.FromDays(1).TotalMilliseconds;
}
[UnitOfWork(isTransactional: false)]
protected override async Task DoWorkAsync(PeriodicBackgroundWorkerContext workerContext)
{
var organizationPremiumEndDateNotifier = workerContext.ServiceProvider.GetRequiredService<OrganizationPremiumEndDateNotifier>();
var organizationRepository = workerContext.ServiceProvider.GetRequiredService<IRepository<Organization, Guid>>();
var asyncExecuter = workerContext.ServiceProvider.GetRequiredService<IAsyncQueryableExecuter>();
var clock = workerContext.ServiceProvider.GetRequiredService<IClock>();
await SendPremiumReminderEmail(organizationRepository, organizationPremiumEndDateNotifier, asyncExecuter, clock);
await UpdatePremiumExpiredOrganization(organizationRepository, asyncExecuter, clock);
}
private async Task SendPremiumReminderEmail(
IRepository<Organization, Guid> organizationRepository,
OrganizationPremiumEndDateNotifier organizationPremiumEndDateNotifier,
IAsyncQueryableExecuter asyncExecuter,
IClock clock)
{
var oneMonthLater = clock.Now.AddMonths(1);
var queryable = await organizationRepository.GetQueryableAsync();
var query = queryable.Where(x =>
x.IsSendPremiumReminderEmail == false &&
x.PremiumEndDate <= oneMonthLater
);
var organizations = await asyncExecuter.ToListAsync(query);
foreach (var organization in organizations)
{
try
{
if (organization.IsPremium)
{
if (organization.PremiumEndDate >= clock.Now)
{
await organizationPremiumEndDateNotifier.NotifyAsync(organization);
}
organization.IsSendPremiumReminderEmail = true;
await organizationRepository.UpdateAsync(organization);
}
}
catch (Exception ex)
{
Logger.LogException(ex);
}
}
}
private async Task UpdatePremiumExpiredOrganization(IRepository<Organization, Guid> organizationRepository, IAsyncQueryableExecuter asyncExecuter, IClock clock)
{
var queryable = await organizationRepository.GetQueryableAsync();
var query = queryable.Where(x =>
x.PremiumEndDate >= clock.Now
);
var organizations = await asyncExecuter.ToListAsync(query);
foreach (var organization in organizations)
{
try
{
if (!organization.IsPremium)
{
continue;
}
organization.DowngradeToPremium();
await organizationRepository.UpdateAsync(organization);
}
catch (Exception ex)
{
Logger.LogException(ex);
}
}
}
}
}

9
src/EventHub.Domain/Emailing/EmailTemplateDefinitionProvider.cs

@ -73,6 +73,15 @@ namespace EventHub.Emailing
isInlineLocalized: true
)
);
context.Add(
new TemplateDefinition(
EmailTemplates.PremiumEndDateReminder)
.WithVirtualFilePath(
"/Emailing/Templates/PremiumEndDateReminder.tpl",
isInlineLocalized: true
)
);
}
}
}

2
src/EventHub.Domain/Emailing/EmailTemplates.cs

@ -15,5 +15,7 @@ namespace EventHub.Emailing
public const string PaymentRequestCompleted = "EventHub.Organization.PaymentRequestCompleted";
public const string PaymentRequestFailed = "EventHub.Organization.PaymentRequestFailed";
public const string PremiumEndDateReminder = "EventHub.Organization.PremiumEndDateReminder";
}
}

334
src/EventHub.Domain/Emailing/Templates/PremiumEndDateReminder.tpl

@ -0,0 +1,334 @@
<!DOCTYPE html>
<html xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office" lang="en">
<head>
<title></title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<!--[if mso]><xml><o:OfficeDocumentSettings><o:PixelsPerInch>96</o:PixelsPerInch><o:AllowPNG/></o:OfficeDocumentSettings></xml><![endif]-->
<style>
* {
box-sizing: border-box;
}
body {
margin: 0;
padding: 0;
}
th.column {
padding: 0
}
a[x-apple-data-detectors] {
color: inherit !important;
text-decoration: inherit !important;
}
#MessageViewBody a {
color: inherit;
text-decoration: none;
}
p {
line-height: inherit
}
@media (max-width:660px) {
.row-content {
width: 100% !important;
}
.stack .column {
width: 100%;
display: block;
}
}
</style>
</head>
<body style="background-color: #f8f8f9; margin: 0; padding: 0; -webkit-text-size-adjust: none; text-size-adjust: none;">
<table class="nl-container" width="100%" border="0" cellpadding="0" cellspacing="0" role="presentation" style="mso-table-lspace: 0pt; mso-table-rspace: 0pt; background-color: #f8f8f9;">
<tbody>
<tr>
<td>
<table class="row row-1" align="center" width="100%" border="0" cellpadding="0" cellspacing="0" role="presentation" style="mso-table-lspace: 0pt; mso-table-rspace: 0pt;">
<tbody>
<tr>
<td>
<table class="row-content stack" align="center" border="0" cellpadding="0" cellspacing="0" role="presentation" style="mso-table-lspace: 0pt; mso-table-rspace: 0pt; background-color: #fff;" width="640">
<tbody>
<tr>
<th class="column" width="100%" style="mso-table-lspace: 0pt; mso-table-rspace: 0pt; font-weight: 400; text-align: left; vertical-align: top; padding-top: 0px; padding-bottom: 0px; border-top: 0px; border-right: 0px; border-bottom: 0px; border-left: 0px;">
<table class="divider_block" width="100%" border="0" cellpadding="0" cellspacing="0" role="presentation" style="mso-table-lspace: 0pt; mso-table-rspace: 0pt;">
<tr>
<td style="padding-bottom:12px;padding-top:60px;">
<div align="center">
<table border="0" cellpadding="0" cellspacing="0" role="presentation" width="100%" style="mso-table-lspace: 0pt; mso-table-rspace: 0pt;">
<tr>
<td class="divider_inner" style="font-size: 1px; line-height: 1px; border-top: 0px solid #BBBBBB;"><span></span></td>
</tr>
</table>
</div>
</td>
</tr>
</table>
<table class="image_block" width="100%" border="0" cellpadding="0" cellspacing="0" role="presentation" style="mso-table-lspace: 0pt; mso-table-rspace: 0pt;">
<tr>
<td style="padding-left:40px;padding-right:40px;width:100%;">
<div align="center" style="line-height:10px"><a href="{{app_url}}" target="_blank" style="outline:none" tabindex="-1"><img src="{{app_url}}//assets/eventhub-logo.svg" style="display: block; height: auto; border: 0; width: 352px; max-width: 100%;" width="352" alt="EventHub" title="EventHub"></a></div>
</td>
</tr>
</table>
<table class="divider_block" width="100%" border="0" cellpadding="0" cellspacing="0" role="presentation" style="mso-table-lspace: 0pt; mso-table-rspace: 0pt;">
<tr>
<td style="padding-top:50px;">
<div align="center">
<table border="0" cellpadding="0" cellspacing="0" role="presentation" width="100%" style="mso-table-lspace: 0pt; mso-table-rspace: 0pt;">
<tr>
<td class="divider_inner" style="font-size: 1px; line-height: 1px; border-top: 0px solid #BBBBBB;"><span></span></td>
</tr>
</table>
</div>
</td>
</tr>
</table>
<table class="text_block" width="100%" border="0" cellpadding="0" cellspacing="0" role="presentation" style="mso-table-lspace: 0pt; mso-table-rspace: 0pt; word-break: break-word;">
<tr>
<td style="padding-bottom:10px;padding-left:40px;padding-right:40px;padding-top:10px;">
<div style="font-family: sans-serif">
<div style="font-size: 12px; color: #555555; line-height: 1.2; font-family: Montserrat, Trebuchet MS, Lucida Grande, Lucida Sans Unicode, Lucida Sans, Tahoma, sans-serif;">
<p style="margin: 0; font-size: 16px; text-align: center;"><span style="font-size:30px;color:#2b303a;"><strong>Your Premium Organization is expiring</strong></span></p>
</div>
</div>
</td>
</tr>
</table>
<table class="text_block" width="100%" border="0" cellpadding="0" cellspacing="0" role="presentation" style="mso-table-lspace: 0pt; mso-table-rspace: 0pt; word-break: break-word;">
<tr>
<td style="padding-bottom:10px;padding-left:40px;padding-right:40px;padding-top:10px;">
<div style="font-family: sans-serif">
<div style="font-size: 12px; font-family: Montserrat, Trebuchet MS, Lucida Grande, Lucida Sans Unicode, Lucida Sans, Tahoma, sans-serif; color: #555555; line-height: 1.5;">
<p style="margin: 0; font-size: 14px; text-align: center;">If you want to take advantage of the privileges, you can extend the premium period.</p>
</div>
</div>
</td>
</tr>
</table>
<table class="divider_block" width="100%" border="0" cellpadding="0" cellspacing="0" role="presentation" style="mso-table-lspace: 0pt; mso-table-rspace: 0pt;">
<tr>
<td style="padding-top:50px;">
<div align="center">
<table border="0" cellpadding="0" cellspacing="0" role="presentation" width="100%" style="mso-table-lspace: 0pt; mso-table-rspace: 0pt;">
<tr>
<td class="divider_inner" style="font-size: 1px; line-height: 1px; border-top: 0px solid #BBBBBB;"><span></span></td>
</tr>
</table>
</div>
</td>
</tr>
</table>
</th>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
<table class="row row-2" align="center" width="100%" border="0" cellpadding="0" cellspacing="0" role="presentation" style="mso-table-lspace: 0pt; mso-table-rspace: 0pt;">
<tbody>
<tr>
<td>
<table class="row-content" align="center" border="0" cellpadding="0" cellspacing="0" role="presentation" style="mso-table-lspace: 0pt; mso-table-rspace: 0pt; background-color: #fff;" width="640">
<tbody>
<tr>
<th class="column" width="50%" style="mso-table-lspace: 0pt; mso-table-rspace: 0pt; font-weight: 400; text-align: left; vertical-align: top;">
<table width="100%" border="0" cellpadding="0" cellspacing="0" role="presentation" style="mso-table-lspace: 0pt; mso-table-rspace: 0pt;">
<tr>
<td style="width:20px;background-color:#FFF">&nbsp;</td>
<td style="background-color:#f3fafa;border-right:8px solid #FFF;border-top:0px;border-bottom:0px;width:300px;">
<table class="divider_block" width="100%" border="0" cellpadding="0" cellspacing="0" role="presentation" style="mso-table-lspace: 0pt; mso-table-rspace: 0pt;">
<tr>
<td>
<div align="center">
<table border="0" cellpadding="0" cellspacing="0" role="presentation" width="100%" style="mso-table-lspace: 0pt; mso-table-rspace: 0pt;">
<tr>
<td class="divider_inner" style="font-size: 1px; line-height: 1px; border-top: 4px solid #D54560;"><span></span></td>
</tr>
</table>
</div>
</td>
</tr>
</table>
<table class="text_block" width="100%" border="0" cellpadding="0" cellspacing="0" role="presentation" style="mso-table-lspace: 0pt; mso-table-rspace: 0pt; word-break: break-word;">
<tr>
<td style="padding-bottom:40px;padding-left:5px;padding-right:5px;padding-top:35px;">
<div style="font-family: sans-serif">
<div style="font-size: 12px; color: #555555; line-height: 1.5; font-family: Montserrat, Trebuchet MS, Lucida Grande, Lucida Sans Unicode, Lucida Sans, Tahoma, sans-serif;">
<p style="margin: 0; font-size: 16px; text-align: center;"><span style="color:#a2a9ad;"><strong>Organization name</strong></span></p>
<p style="margin: 0; font-size: 16px; text-align: center;"><span style="color:#2b303a;"><span style="font-size:20px;"><strong>{{model.organization_name}}</strong></span></span></p>
</div>
</div>
</td>
</tr>
</table>
</td>
</tr>
</table>
</th>
<th class="column" width="50%" style="mso-table-lspace: 0pt; mso-table-rspace: 0pt; font-weight: 400; text-align: left; vertical-align: top;">
<table width="100%" border="0" cellpadding="0" cellspacing="0" role="presentation" style="mso-table-lspace: 0pt; mso-table-rspace: 0pt;">
<tr>
<td style="background-color:#f3fafa;border-left:8px solid #FFF;border-top:0px;border-bottom:0px;width:300px;">
<table class="divider_block" width="100%" border="0" cellpadding="0" cellspacing="0" role="presentation" style="mso-table-lspace: 0pt; mso-table-rspace: 0pt;">
<tr>
<td>
<div align="center">
<table border="0" cellpadding="0" cellspacing="0" role="presentation" width="100%" style="mso-table-lspace: 0pt; mso-table-rspace: 0pt;">
<tr>
<td class="divider_inner" style="font-size: 1px; line-height: 1px; border-top: 4px solid #D54560;"><span></span></td>
</tr>
</table>
</div>
</td>
</tr>
</table>
<table class="text_block" width="100%" border="0" cellpadding="0" cellspacing="0" role="presentation" style="mso-table-lspace: 0pt; mso-table-rspace: 0pt; word-break: break-word;">
<tr>
<td style="padding-bottom:40px;padding-left:5px;padding-right:5px;padding-top:35px;">
<div style="font-family: sans-serif">
<div style="font-size: 12px; color: #555555; line-height: 1.5; font-family: Montserrat, Trebuchet MS, Lucida Grande, Lucida Sans Unicode, Lucida Sans, Tahoma, sans-serif;">
<p style="margin: 0; font-size: 16px; text-align: center; mso-line-height-alt: 18px;"><span style="color:#a2a9ad;font-size:12px;"><strong>End Date</strong></span></p>
<p style="margin: 0; font-size: 16px; text-align: center;"><span style="color:#2b303a;"><span style="font-size:20px;"><strong>{{model.end_date}}</strong></span></span></p>
</div>
</div>
</td>
</tr>
</table>
</td>
<td style="width:20px;background-color:#FFF">&nbsp;</td>
</tr>
</table>
</th>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
<table class="row row-3" align="center" width="100%" border="0" cellpadding="0" cellspacing="0" role="presentation" style="mso-table-lspace: 0pt; mso-table-rspace: 0pt;">
<tbody>
<tr>
<td>
<table class="row-content stack" align="center" border="0" cellpadding="0" cellspacing="0" role="presentation" style="mso-table-lspace: 0pt; mso-table-rspace: 0pt; background-color: #fff;" width="640">
<tbody>
<tr>
<th class="column" width="100%" style="mso-table-lspace: 0pt; mso-table-rspace: 0pt; font-weight: 400; text-align: left; vertical-align: top; padding-top: 0px; padding-bottom: 0px; border-top: 0px; border-right: 0px; border-bottom: 0px; border-left: 0px;">
<table class="button_block" width="100%" border="0" cellpadding="0" cellspacing="0" role="presentation" style="mso-table-lspace: 0pt; mso-table-rspace: 0pt;">
<tr>
<td style="padding-left:10px;padding-right:10px;padding-top:20px;text-align:center;">
<div align="center">
<!--[if mso]><v:roundrect xmlns:v="urn:schemas-microsoft-com:vml" xmlns:w="urn:schemas-microsoft-com:office:word" href="{{app_url}}/pricing/{{model.organization_name}}" style="height:58px;width:134px;v-text-anchor:middle;" arcsize="104%" stroke="false" fillcolor="#d54560"><w:anchorlock/><v:textbox inset="0px,0px,0px,0px"><center style="color:#ffffff; font-family:Tahoma, sans-serif; font-size:14px"><![endif]--><a href="{{app_url}}/pricing/{{model.organization_name}}" target="_blank" style="text-decoration:none;display:inline-block;color:#ffffff;background-color:#d54560;border-radius:60px;width:auto;border-top:1px solid #d54560;border-right:1px solid #d54560;border-bottom:1px solid #d54560;border-left:1px solid #d54560;padding-top:15px;padding-bottom:15px;font-family:Montserrat, Trebuchet MS, Lucida Grande, Lucida Sans Unicode, Lucida Sans, Tahoma, sans-serif;text-align:center;mso-border-alt:none;word-break:keep-all;"><span style="padding-left:30px;padding-right:30px;font-size:14px;display:inline-block;letter-spacing:normal;"><span style="font-size: 12px; line-height: 2; word-break: break-word; mso-line-height-alt: 24px;"><span style="font-size: 14px; line-height: 28px;" data-mce-style="font-size: 14px; line-height: 28px;">Extend Now</span></span></span></a>
<!--[if mso]></center></v:textbox></v:roundrect><![endif]-->
</div>
</td>
</tr>
</table>
<table class="divider_block" width="100%" border="0" cellpadding="0" cellspacing="0" role="presentation" style="mso-table-lspace: 0pt; mso-table-rspace: 0pt;">
<tr>
<td style="padding-bottom:12px;padding-top:24px;">
<div align="center">
<table border="0" cellpadding="0" cellspacing="0" role="presentation" width="100%" style="mso-table-lspace: 0pt; mso-table-rspace: 0pt;">
<tr>
<td class="divider_inner" style="font-size: 1px; line-height: 1px; border-top: 0px solid #BBBBBB;"><span></span></td>
</tr>
</table>
</div>
</td>
</tr>
</table>
</th>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
<table class="row row-4" align="center" width="100%" border="0" cellpadding="0" cellspacing="0" role="presentation" style="mso-table-lspace: 0pt; mso-table-rspace: 0pt;">
<tbody>
<tr>
<td>
<table class="row-content stack" align="center" border="0" cellpadding="0" cellspacing="0" role="presentation" style="mso-table-lspace: 0pt; mso-table-rspace: 0pt; background-color: #2b303a;" width="640">
<tbody>
<tr>
<th class="column" width="100%" style="mso-table-lspace: 0pt; mso-table-rspace: 0pt; font-weight: 400; text-align: left; vertical-align: top; padding-top: 0px; padding-bottom: 0px; border-top: 0px; border-right: 0px; border-bottom: 0px; border-left: 0px;">
<table class="divider_block" width="100%" border="0" cellpadding="0" cellspacing="0" role="presentation" style="mso-table-lspace: 0pt; mso-table-rspace: 0pt;">
<tr>
<td>
<div align="center">
<table border="0" cellpadding="0" cellspacing="0" role="presentation" width="100%" style="mso-table-lspace: 0pt; mso-table-rspace: 0pt;">
<tr>
<td class="divider_inner" style="font-size: 1px; line-height: 1px; border-top: 4px solid #D54560;"><span></span></td>
</tr>
</table>
</div>
</td>
</tr>
</table>
<table class="html_block" width="100%" border="0" cellpadding="0" cellspacing="0" role="presentation" style="mso-table-lspace: 0pt; mso-table-rspace: 0pt;">
<tr>
<td>
<div style="font-family:Montserrat, Trebuchet MS, Lucida Grande, Lucida Sans Unicode, Lucida Sans, Tahoma, sans-serif;" align="center"><div class="cont" style=" padding: 25px 0px 0; margin-top: 0px;">
<a href="{{app_url}}" style="font-size: 14px; font-family: Arial, sans-serif; color: #777; font-weight: bold; margin-right: 30px; margin-bottom: 20px; text-decoration: none; display: inline-block;">Home</a>
<a href="{{app_url}}/events" style="font-size: 14px; font-family: Arial, sans-serif; color: #777; font-weight: bold; margin-right: 30px; margin-bottom: 20px; text-decoration: none; display: inline-block;">Events</a>
<a href="{{app_url}}/organizations" style="font-size: 14px; font-family: Arial, sans-serif; color: #777; font-weight: bold; margin-right: 30px; margin-bottom: 20px; text-decoration: none; display: inline-block;">Organizations</a>
<a href="{{app_url}}/terms-service" style="font-size: 14px; font-family: Arial, sans-serif; color: #777; font-weight: bold; margin-right: 30px; margin-bottom: 20px; text-decoration: none; display: inline-block;">Term
of Service</a>
<a href="{{app_url}}/privacy-policy" style="font-size: 14px; font-family: Arial, sans-serif; color: #777; font-weight: bold; margin-right: 0px; margin-bottom: 20px; text-decoration: none; display: inline-block;">Privacy
Policy</a>
</div></div>
</td>
</tr>
</table>
<table class="divider_block" width="100%" border="0" cellpadding="0" cellspacing="0" role="presentation" style="mso-table-lspace: 0pt; mso-table-rspace: 0pt;">
<tr>
<td style="padding-bottom:10px;padding-left:40px;padding-right:40px;padding-top:10px;">
<div align="center">
<table border="0" cellpadding="0" cellspacing="0" role="presentation" width="100%" style="mso-table-lspace: 0pt; mso-table-rspace: 0pt;">
<tr>
<td class="divider_inner" style="font-size: 1px; line-height: 1px; border-top: 1px solid #555961;"><span></span></td>
</tr>
</table>
</div>
</td>
</tr>
</table>
<table class="text_block" width="100%" border="0" cellpadding="0" cellspacing="0" role="presentation" style="mso-table-lspace: 0pt; mso-table-rspace: 0pt; word-break: break-word;">
<tr>
<td style="padding-bottom:30px;padding-left:40px;padding-right:40px;padding-top:20px;">
<div style="font-family: sans-serif">
<div style="font-size: 12px; font-family: Montserrat, Trebuchet MS, Lucida Grande, Lucida Sans Unicode, Lucida Sans, Tahoma, sans-serif; color: #555555; line-height: 1.2;">
<p style="margin: 0; font-size: 14px; text-align: center;"><span style="color:#95979c;font-size:12px;">EventHub - Powered by Volosoft</span></p>
</div>
</div>
</td>
</tr>
</table>
</th>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table><!-- End -->
</body>
</html>

9
src/EventHub.Domain/Organizations/Organization.cs

@ -33,6 +33,8 @@ namespace EventHub.Organizations
public DateTime? PremiumEndDate { get; private set; }
public bool IsSendPremiumReminderEmail { get; set; }
private Organization()
{
}
@ -76,8 +78,13 @@ namespace EventHub.Organizations
return this;
}
internal Organization DowngradeToPremium(IClock clock)
public Organization DowngradeToPremium()
{
if (!IsPremium)
{
return this;
}
SetPremiumStatus(false);
return this;

2707
src/EventHub.EntityFrameworkCore/Migrations/20211027131803_Added_IsSendPremiumReminderEmail_To_Organization.Designer.cs

File diff suppressed because it is too large

26
src/EventHub.EntityFrameworkCore/Migrations/20211027131803_Added_IsSendPremiumReminderEmail_To_Organization.cs

@ -0,0 +1,26 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace EventHub.Migrations
{
public partial class Added_IsSendPremiumReminderEmail_To_Organization : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn<bool>(
name: "IsSendPremiumReminderEmail",
table: "EhOrganizations",
type: "boolean",
nullable: false,
defaultValue: false);
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "IsSendPremiumReminderEmail",
table: "EhOrganizations");
}
}
}

3
src/EventHub.EntityFrameworkCore/Migrations/EventHubDbContextModelSnapshot.cs

@ -305,6 +305,9 @@ namespace EventHub.Migrations
b.Property<bool>("IsPremium")
.HasColumnType("boolean");
b.Property<bool>("IsSendPremiumReminderEmail")
.HasColumnType("boolean");
b.Property<DateTime?>("LastModificationTime")
.HasColumnType("timestamp with time zone")
.HasColumnName("LastModificationTime");

2
src/EventHub.Web/Pages/Pricing.cshtml

@ -1,4 +1,4 @@
@page
@page "/pricing/{organizationName}"
@using EventHub.Localization
@using Microsoft.AspNetCore.Mvc.Localization
@model EventHub.Web.Pages.Pricing

12
src/EventHub.Web/Pages/Pricing.cshtml.cs

@ -45,17 +45,17 @@ namespace EventHub.Web.Pages
public async Task OnGetAsync()
{
if (_premiumPlanInfoOptionsSnapshot.Value.IsActive)
{
PremiumPlanInfo = _premiumPlanInfoOptionsSnapshot.Value;
}
Organization = await _organizationAppService.GetProfileAsync(OrganizationName);
if (CurrentUser.UserName != Organization.OwnerUserName)
{
throw new AbpAuthorizationException();
}
if (_premiumPlanInfoOptionsSnapshot.Value.IsActive)
{
PremiumPlanInfo = _premiumPlanInfoOptionsSnapshot.Value;
}
}
public async Task<IActionResult> OnPostUpgradeAsync()

Loading…
Cancel
Save