DocSpace-buildtools/common/ASC.Core.Common/Billing/TariffService.cs

695 lines
27 KiB
C#
Raw Normal View History

2019-05-15 14:56:09 +00:00
/*
*
* (c) Copyright Ascensio System Limited 2010-2018
*
* This program is freeware. You can redistribute it and/or modify it under the terms of the GNU
* General Public License (GPL) version 3 as published by the Free Software Foundation (https://www.gnu.org/copyleft/gpl.html).
* In accordance with Section 7(a) of the GNU GPL its Section 15 shall be amended to the effect that
* Ascensio System SIA expressly excludes the warranty of non-infringement of any third-party rights.
*
* THIS PROGRAM IS DISTRIBUTED WITHOUT ANY WARRANTY; WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR
* FITNESS FOR A PARTICULAR PURPOSE. For more details, see GNU GPL at https://www.gnu.org/copyleft/gpl.html
*
* You can contact Ascensio System SIA by email at sales@onlyoffice.com
*
* The interactive user interfaces in modified source and object code versions of ONLYOFFICE must display
* Appropriate Legal Notices, as required under Section 5 of the GNU GPL version 3.
*
* Pursuant to Section 7 § 3(b) of the GNU GPL you must retain the original ONLYOFFICE logo which contains
* relevant author attributions when distributing the software. If the display of the logo in its graphic
* form is not reasonably feasible for technical reasons, you must include the words "Powered by ONLYOFFICE"
* in every copy of the program you distribute.
* Pursuant to Section 7 § 3(e) we decline to grant you any rights under trademark law for use of our trademarks.
*
*/
namespace ASC.Core.Billing
2020-10-19 15:53:15 +00:00
{
[Singletone]
2019-10-31 11:28:30 +00:00
public class TariffServiceStorage
{
public ICache Cache { get; }
internal ICacheNotify<TariffCacheItem> Notify { get; }
2019-10-31 11:28:30 +00:00
public TariffServiceStorage(ICacheNotify<TariffCacheItem> notify, ICache cache)
2019-05-15 14:56:09 +00:00
{
2021-01-12 17:51:14 +00:00
Cache = cache;
2019-10-11 15:03:03 +00:00
Notify = notify;
Notify.Subscribe((i) =>
2019-05-15 14:56:09 +00:00
{
2019-10-11 15:03:03 +00:00
Cache.Remove(TariffService.GetTariffCacheKey(i.TenantId));
Cache.Remove(TariffService.GetBillingUrlCacheKey(i.TenantId));
2021-05-17 11:35:00 +00:00
Cache.Remove(TariffService.GetBillingPaymentCacheKey(i.TenantId)); // clear all payments
}, ASC.Common.Caching.CacheNotifyAction.Remove);
2019-05-15 14:56:09 +00:00
//TODO: Change code of WCF -> not supported in .NET standard/.Net Core
/*try
{
var section = (ClientSection)ConfigurationManager.GetSection("system.serviceModel/client");
if (section != null)
{
billingConfigured = section.Endpoints.Cast<ChannelEndpointElement>()
.Any(e => e.Contract == typeof(IService).FullName);
}
}
catch (Exception err)
{
log.Error(err);
}*/
2019-10-31 11:28:30 +00:00
}
}
2020-10-22 17:57:18 +00:00
[Scope]
2020-02-20 08:05:10 +00:00
class ConfigureTariffService : IConfigureNamedOptions<TariffService>
{
public ConfigureTariffService(
IOptionsSnapshot<CachedQuotaService> quotaService,
IOptionsSnapshot<CachedTenantService> tenantService,
CoreBaseSettings coreBaseSettings,
CoreSettings coreSettings,
IConfiguration configuration,
DbContextManager<CoreDbContext> coreDbContextManager,
TariffServiceStorage tariffServiceStorage,
IOptionsMonitor<ILog> iLog)
{
QuotaService = quotaService;
TenantService = tenantService;
CoreBaseSettings = coreBaseSettings;
CoreSettings = coreSettings;
Configuration = configuration;
CoreDbContextManager = coreDbContextManager;
TariffServiceStorage = tariffServiceStorage;
ILog = iLog;
}
2020-08-12 09:58:08 +00:00
private IOptionsSnapshot<CachedQuotaService> QuotaService { get; }
private IOptionsSnapshot<CachedTenantService> TenantService { get; }
private CoreBaseSettings CoreBaseSettings { get; }
private CoreSettings CoreSettings { get; }
private IConfiguration Configuration { get; }
private DbContextManager<CoreDbContext> CoreDbContextManager { get; }
private TariffServiceStorage TariffServiceStorage { get; }
private IOptionsMonitor<ILog> ILog { get; }
2020-02-20 08:05:10 +00:00
public void Configure(string name, TariffService options)
{
Configure(options);
options.QuotaService = QuotaService.Get(name);
options.TenantService = TenantService.Get(name);
2020-10-18 19:00:38 +00:00
options.LazyCoreDbContext = new Lazy<CoreDbContext>(() => CoreDbContextManager.Get(name));
2020-02-20 08:05:10 +00:00
}
public void Configure(TariffService options)
{
options.Log = ILog.CurrentValue;
options.CoreSettings = CoreSettings;
options.Configuration = Configuration;
options.TariffServiceStorage = TariffServiceStorage;
options.Options = ILog;
options.CoreBaseSettings = CoreBaseSettings;
options.Test = Configuration["core:payment:test"] == "true";
int.TryParse(Configuration["core:payment:delay"], out var paymentDelay);
options.PaymentDelay = paymentDelay;
options.Cache = TariffServiceStorage.Cache;
options.Notify = TariffServiceStorage.Notify;
options.QuotaService = QuotaService.Value;
options.TenantService = TenantService.Value;
2020-10-18 19:00:38 +00:00
options.LazyCoreDbContext = new Lazy<CoreDbContext>(() => CoreDbContextManager.Value);
2020-02-20 08:05:10 +00:00
}
}
2019-05-15 14:56:09 +00:00
2019-11-29 12:26:53 +00:00
public class TariffService : ITariffService
2019-10-31 11:28:30 +00:00
{
2019-10-11 15:03:03 +00:00
private const int DEFAULT_TRIAL_PERIOD = 30;
private static readonly TimeSpan DEFAULT_CACHE_EXPIRATION = TimeSpan.FromMinutes(5);
private static readonly TimeSpan STANDALONE_CACHE_EXPIRATION = TimeSpan.FromMinutes(15);
2020-02-20 08:05:10 +00:00
internal ICache Cache { get; set; }
internal ICacheNotify<TariffCacheItem> Notify { get; set; }
2020-02-20 08:05:10 +00:00
internal ILog Log { get; set; }
internal IQuotaService QuotaService { get; set; }
internal ITenantService TenantService { get; set; }
internal bool Test { get; set; }
internal int PaymentDelay { get; set; }
2019-10-11 15:03:03 +00:00
2019-10-31 11:28:30 +00:00
public TimeSpan CacheExpiration { get; set; }
2020-08-12 09:58:08 +00:00
internal CoreBaseSettings CoreBaseSettings { get; set; }
internal CoreSettings CoreSettings { get; set; }
internal IConfiguration Configuration { get; set; }
2020-10-18 19:00:38 +00:00
internal CoreDbContext CoreDbContext { get => LazyCoreDbContext.Value; }
internal Lazy<CoreDbContext> LazyCoreDbContext { get; set; }
2020-08-12 09:58:08 +00:00
internal TariffServiceStorage TariffServiceStorage { get; set; }
internal IOptionsMonitor<ILog> Options { get; set; }
2021-05-17 11:35:00 +00:00
public BillingClient BillingClient { get; }
public readonly int ACTIVE_USERS_MIN;
public readonly int ACTIVE_USERS_MAX;
2019-10-31 11:28:30 +00:00
2020-02-20 08:05:10 +00:00
public TariffService()
2019-12-17 08:27:38 +00:00
{
2020-02-20 08:05:10 +00:00
CacheExpiration = DEFAULT_CACHE_EXPIRATION;
2019-12-17 08:27:38 +00:00
}
2020-02-20 14:57:48 +00:00
public TariffService(
2019-10-31 11:28:30 +00:00
IQuotaService quotaService,
ITenantService tenantService,
CoreBaseSettings coreBaseSettings,
CoreSettings coreSettings,
2019-12-17 08:27:38 +00:00
IConfiguration configuration,
2020-02-20 14:57:48 +00:00
DbContextManager<CoreDbContext> coreDbContextManager,
2019-10-31 11:28:30 +00:00
TariffServiceStorage tariffServiceStorage,
2021-05-17 11:35:00 +00:00
IOptionsMonitor<ILog> options,
Users.Constants constants,
2021-05-17 11:35:00 +00:00
BillingClient billingClient)
2020-02-20 14:57:48 +00:00
: this()
2020-02-17 08:58:14 +00:00
2019-10-31 11:28:30 +00:00
{
2020-02-20 14:57:48 +00:00
Log = options.CurrentValue;
QuotaService = quotaService;
TenantService = tenantService;
2019-10-31 11:28:30 +00:00
CoreSettings = coreSettings;
2020-02-17 08:58:14 +00:00
Configuration = configuration;
2019-10-31 11:28:30 +00:00
TariffServiceStorage = tariffServiceStorage;
2021-05-17 11:35:00 +00:00
Options = options;
BillingClient = billingClient;
2019-09-18 15:19:30 +00:00
CoreBaseSettings = coreBaseSettings;
2020-02-20 14:57:48 +00:00
Test = configuration["core:payment:test"] == "true";
int.TryParse(configuration["core:payment:delay"], out var paymentDelay);
2019-10-31 11:28:30 +00:00
2020-02-20 14:57:48 +00:00
PaymentDelay = paymentDelay;
2020-02-17 08:58:14 +00:00
2020-02-20 14:57:48 +00:00
Cache = TariffServiceStorage.Cache;
Notify = TariffServiceStorage.Notify;
2021-05-17 11:35:00 +00:00
LazyCoreDbContext = new Lazy<CoreDbContext>(() => coreDbContextManager.Value);
var range = (Configuration["core.payment-user-range"] ?? "").Split('-');
if (!int.TryParse(range[0], out ACTIVE_USERS_MIN))
{
ACTIVE_USERS_MIN = 0;
}
if (range.Length < 2 || !int.TryParse(range[1], out ACTIVE_USERS_MAX))
{
ACTIVE_USERS_MAX = constants.MaxEveryoneCount;
}
2019-12-17 08:27:38 +00:00
}
2019-05-15 14:56:09 +00:00
public Tariff GetTariff(int tenantId, bool withRequestToPaymentSystem = true)
{
//single tariff for all portals
2019-09-18 15:19:30 +00:00
if (CoreBaseSettings.Standalone)
2019-05-15 14:56:09 +00:00
tenantId = -1;
var key = GetTariffCacheKey(tenantId);
2020-02-20 08:05:10 +00:00
var tariff = Cache.Get<Tariff>(key);
2019-05-15 14:56:09 +00:00
if (tariff == null)
{
2021-05-17 11:35:00 +00:00
tariff = GetBillingInfo(tenantId);
2019-05-15 14:56:09 +00:00
tariff = CalculateTariff(tenantId, tariff);
2020-02-20 08:05:10 +00:00
Cache.Insert(key, tariff, DateTime.UtcNow.Add(GetCacheExpiration()));
2019-05-15 14:56:09 +00:00
2021-05-17 11:35:00 +00:00
if (BillingClient.Configured && withRequestToPaymentSystem)
2019-05-15 14:56:09 +00:00
{
2020-10-12 19:39:23 +00:00
Task.Run(() =>
2020-09-30 11:50:39 +00:00
{
try
{
2021-05-17 11:35:00 +00:00
var client = GetBillingClient();
var lastPayment = client.GetLastPayment(GetPortalId(tenantId));
var quota = QuotaService.GetTenantQuotas().SingleOrDefault(q => q.AvangateId == lastPayment.ProductId);
2020-09-30 11:50:39 +00:00
if (quota == null)
{
2022-01-14 13:12:37 +00:00
throw new InvalidOperationException($"Quota with id {lastPayment.ProductId} not found for portal {GetPortalId(tenantId)}.");
2020-09-30 11:50:39 +00:00
}
2021-05-17 11:35:00 +00:00
2020-09-30 11:50:39 +00:00
var asynctariff = Tariff.CreateDefault();
asynctariff.QuotaId = quota.Id;
2021-05-17 11:35:00 +00:00
asynctariff.Autorenewal = lastPayment.Autorenewal;
asynctariff.DueDate = 9999 <= lastPayment.EndDate.Year ? DateTime.MaxValue : lastPayment.EndDate;
2020-09-30 11:50:39 +00:00
2021-05-17 11:35:00 +00:00
if (quota.ActiveUsers == -1
&& lastPayment.Quantity < ACTIVE_USERS_MIN)
{
throw new BillingException(string.Format("The portal {0} is paid for {1} users", tenantId, lastPayment.Quantity));
}
asynctariff.Quantity = lastPayment.Quantity;
if (SaveBillingInfo(tenantId, asynctariff, false))
2020-09-30 11:50:39 +00:00
{
asynctariff = CalculateTariff(tenantId, asynctariff);
ClearCache(tenantId);
Cache.Insert(key, asynctariff, DateTime.UtcNow.Add(GetCacheExpiration()));
}
}
2021-05-17 11:35:00 +00:00
catch (BillingNotFoundException)
{
}
2020-09-30 11:50:39 +00:00
catch (Exception error)
{
2021-05-17 11:35:00 +00:00
LogError(error, tenantId.ToString());
2020-09-30 11:50:39 +00:00
}
});
2019-05-15 14:56:09 +00:00
}
}
return tariff;
}
public void SetTariff(int tenantId, Tariff tariff)
{
if (tariff == null)
{
2022-01-24 10:49:00 +00:00
throw new ArgumentNullException(nameof(tariff));
2019-05-15 14:56:09 +00:00
}
2020-02-20 08:05:10 +00:00
var q = QuotaService.GetTenantQuota(tariff.QuotaId);
2019-05-15 14:56:09 +00:00
if (q == null) return;
2021-05-17 11:35:00 +00:00
SaveBillingInfo(tenantId, tariff);
2019-05-15 14:56:09 +00:00
if (q.Trial)
{
// reset trial date
2020-02-20 08:05:10 +00:00
var tenant = TenantService.GetTenant(tenantId);
2019-05-15 14:56:09 +00:00
if (tenant != null)
{
tenant.VersionChanged = DateTime.UtcNow;
2020-02-20 08:05:10 +00:00
TenantService.SaveTenant(CoreSettings, tenant);
2019-05-15 14:56:09 +00:00
}
}
ClearCache(tenantId);
}
2019-10-11 15:03:03 +00:00
internal static string GetTariffCacheKey(int tenantId)
2019-05-15 14:56:09 +00:00
{
return string.Format("{0}:{1}", tenantId, "tariff");
}
2019-10-11 15:03:03 +00:00
internal static string GetBillingUrlCacheKey(int tenantId)
2019-05-15 14:56:09 +00:00
{
return string.Format("{0}:{1}", tenantId, "billing:urls");
}
2021-05-17 11:35:00 +00:00
internal static string GetBillingPaymentCacheKey(int tenantId)
{
return string.Format("{0}:{1}", tenantId, "billing:payments");
2019-05-15 14:56:09 +00:00
}
public void ClearCache(int tenantId)
{
Notify.Publish(new TariffCacheItem { TenantId = tenantId }, ASC.Common.Caching.CacheNotifyAction.Remove);
2019-05-15 14:56:09 +00:00
}
2021-05-17 11:35:00 +00:00
public IEnumerable<PaymentInfo> GetPayments(int tenantId)
{
var key = GetBillingPaymentCacheKey(tenantId);
var payments = Cache.Get<List<PaymentInfo>>(key);
if (payments == null)
{
payments = new List<PaymentInfo>();
if (BillingClient.Configured)
{
try
2021-11-12 12:33:03 +00:00
{
2021-05-17 11:35:00 +00:00
var quotas = QuotaService.GetTenantQuotas();
var client = GetBillingClient();
foreach (var pi in client.GetPayments(GetPortalId(tenantId)))
{
var quota = quotas.SingleOrDefault(q => q.AvangateId == pi.ProductRef);
if (quota != null)
{
pi.QuotaId = quota.Id;
}
payments.Add(pi);
}
}
catch (Exception error)
{
LogError(error, tenantId.ToString());
}
}
Cache.Insert(key, payments, DateTime.UtcNow.Add(TimeSpan.FromMinutes(10)));
}
return payments;
}
2019-05-15 14:56:09 +00:00
2021-05-17 11:35:00 +00:00
public Uri GetShoppingUri(int? tenant, int quotaId, string affiliateId, string currency = null, string language = null, string customerId = null, string quantity = null)
2019-05-15 14:56:09 +00:00
{
2020-02-20 08:05:10 +00:00
var quota = QuotaService.GetTenantQuota(quotaId);
2019-05-15 14:56:09 +00:00
if (quota == null) return null;
var key = tenant.HasValue
? GetBillingUrlCacheKey(tenant.Value)
2022-01-14 13:12:37 +00:00
: string.Format($"notenant{(!string.IsNullOrEmpty(affiliateId) ? "_" + affiliateId : "")}");
2019-05-15 14:56:09 +00:00
key += quota.Visible ? "" : "0";
2020-02-20 08:05:10 +00:00
if (!(Cache.Get<Dictionary<string, Tuple<Uri, Uri>>>(key) is IDictionary<string, Tuple<Uri, Uri>> urls))
2019-05-15 14:56:09 +00:00
{
urls = new Dictionary<string, Tuple<Uri, Uri>>();
2021-05-17 11:35:00 +00:00
if (BillingClient.Configured)
2019-05-15 14:56:09 +00:00
{
try
{
2020-02-20 08:05:10 +00:00
var products = QuotaService.GetTenantQuotas()
2019-05-15 14:56:09 +00:00
.Where(q => !string.IsNullOrEmpty(q.AvangateId) && q.Visible == quota.Visible)
.Select(q => q.AvangateId)
2021-05-17 11:35:00 +00:00
.ToArray();
var client = GetBillingClient();
urls =
client.GetPaymentUrls(
tenant.HasValue ? GetPortalId(tenant.Value) : null,
products,
tenant.HasValue ? GetAffiliateId(tenant.Value) : affiliateId,
tenant.HasValue ? GetCampaign(tenant.Value) : null,
!string.IsNullOrEmpty(currency) ? "__Currency__" : null,
!string.IsNullOrEmpty(language) ? "__Language__" : null,
!string.IsNullOrEmpty(customerId) ? "__CustomerID__" : null,
!string.IsNullOrEmpty(quantity) ? "__Quantity__" : null
);
2019-05-15 14:56:09 +00:00
}
catch (Exception error)
{
2020-02-20 08:05:10 +00:00
Log.Error(error);
2019-05-15 14:56:09 +00:00
}
}
2020-02-20 08:05:10 +00:00
Cache.Insert(key, urls, DateTime.UtcNow.Add(TimeSpan.FromMinutes(10)));
2019-05-15 14:56:09 +00:00
}
ResetCacheExpiration();
2021-05-17 11:35:00 +00:00
if (!string.IsNullOrEmpty(quota.AvangateId) && urls.TryGetValue(quota.AvangateId, out var tuple))
{
var result = tuple.Item2;
2019-05-15 14:56:09 +00:00
2021-05-17 11:35:00 +00:00
if (result == null)
{
result = tuple.Item1;
}
else
{
var tariff = tenant.HasValue ? GetTariff(tenant.Value) : null;
if (tariff == null || tariff.QuotaId == quotaId || tariff.State >= TariffState.Delay)
{
result = tuple.Item1;
}
}
if (result == null) return null;
result = new Uri(result.ToString()
.Replace("__Currency__", HttpUtility.UrlEncode(currency ?? ""))
.Replace("__Language__", HttpUtility.UrlEncode((language ?? "").ToLower()))
.Replace("__CustomerID__", HttpUtility.UrlEncode(customerId ?? ""))
.Replace("__Quantity__", HttpUtility.UrlEncode(quantity ?? "")));
return result;
2019-05-15 14:56:09 +00:00
}
return null;
}
2021-05-17 11:35:00 +00:00
public IDictionary<string, Dictionary<string, decimal>> GetProductPriceInfo(params string[] productIds)
{
if (productIds == null)
{
2022-01-24 10:49:00 +00:00
throw new ArgumentNullException(nameof(productIds));
2021-05-17 11:35:00 +00:00
}
try
{
var key = "biling-prices" + string.Join(",", productIds);
var result = Cache.Get<IDictionary<string, Dictionary<string, decimal>>>(key);
if (result == null)
{
var client = GetBillingClient();
result = client.GetProductPriceInfo(productIds);
Cache.Insert(key, result, DateTime.Now.AddHours(1));
}
return result;
}
catch (Exception error)
{
LogError(error);
return productIds
.Select(p => new { ProductId = p, Prices = new Dictionary<string, decimal>() })
.ToDictionary(e => e.ProductId, e => e.Prices);
}
2019-05-15 14:56:09 +00:00
}
public string GetButton(int tariffId, string partnerId)
2020-02-17 08:58:14 +00:00
{
return CoreDbContext.Buttons
.Where(r => r.TariffId == tariffId && r.PartnerId == partnerId)
.Select(r => r.ButtonUrl)
2019-11-29 12:26:53 +00:00
.SingleOrDefault();
2019-05-15 14:56:09 +00:00
}
public void SaveButton(int tariffId, string partnerId, string buttonUrl)
2020-02-17 08:58:14 +00:00
{
var efButton = new DbButton()
{
TariffId = tariffId,
PartnerId = partnerId,
ButtonUrl = buttonUrl
};
CoreDbContext.AddOrUpdate(r => r.Buttons, efButton);
2019-11-29 12:26:53 +00:00
CoreDbContext.SaveChanges();
2019-05-15 14:56:09 +00:00
}
2021-05-17 11:35:00 +00:00
private Tariff GetBillingInfo(int tenant)
2020-02-17 08:58:14 +00:00
{
var r = CoreDbContext.Tariffs
.Where(r => r.Tenant == tenant)
.OrderByDescending(r => r.Id)
2021-11-12 12:33:03 +00:00
.FirstOrDefault();
2021-05-17 11:35:00 +00:00
if (r == null) return Tariff.CreateDefault();
var tariff = Tariff.CreateDefault();
tariff.QuotaId = r.Tariff;
tariff.DueDate = r.Stamp.Year < 9999 ? r.Stamp : DateTime.MaxValue;
tariff.Quantity = r.Quantity;
return tariff;
2019-05-15 14:56:09 +00:00
}
2021-05-17 11:35:00 +00:00
private bool SaveBillingInfo(int tenant, Tariff tariffInfo, bool renewal = true)
2019-05-15 14:56:09 +00:00
{
2021-05-17 11:35:00 +00:00
var inserted = false;
var currentTariff = GetBillingInfo(tenant);
if (!tariffInfo.EqualsByParams(currentTariff))
2019-05-15 14:56:09 +00:00
{
2020-02-17 08:58:14 +00:00
using var tx = CoreDbContext.Database.BeginTransaction();
// last record is not the same
2022-01-18 13:54:24 +00:00
var any = CoreDbContext.Tariffs
.Any(r => r.Tenant == tenant && r.Tariff == tariffInfo.QuotaId && r.Stamp == tariffInfo.DueDate && r.Quantity == tariffInfo.Quantity);
2021-05-17 11:35:00 +00:00
2022-01-18 13:54:24 +00:00
if (tariffInfo.DueDate == DateTime.MaxValue || renewal || any)
2020-02-17 08:58:14 +00:00
{
var efTariff = new DbTariff
{
Tenant = tenant,
2021-05-17 11:35:00 +00:00
Tariff = tariffInfo.QuotaId,
Stamp = tariffInfo.DueDate,
Quantity = tariffInfo.Quantity,
CreateOn = DateTime.UtcNow
2020-02-17 08:58:14 +00:00
};
CoreDbContext.Tariffs.Add(efTariff);
CoreDbContext.SaveChanges();
2019-11-29 12:26:53 +00:00
2020-02-20 08:05:10 +00:00
Cache.Remove(GetTariffCacheKey(tenant));
2019-10-31 11:28:30 +00:00
inserted = true;
}
2019-08-15 15:08:40 +00:00
tx.Commit();
2019-05-15 14:56:09 +00:00
}
if (inserted)
{
2020-02-20 08:05:10 +00:00
var t = TenantService.GetTenant(tenant);
2019-05-15 14:56:09 +00:00
if (t != null)
{
// update tenant.LastModified to flush cache in documents
2020-02-20 08:05:10 +00:00
TenantService.SaveTenant(CoreSettings, t);
2019-05-15 14:56:09 +00:00
}
}
return inserted;
}
public void DeleteDefaultBillingInfo()
{
2020-02-17 08:58:14 +00:00
const int tenant = Tenant.DEFAULT_TENANT;
var tariffs = CoreDbContext.Tariffs.Where(r => r.Tenant == tenant).ToList();
foreach (var t in tariffs)
{
t.Tenant = -2;
}
2019-11-29 12:26:53 +00:00
CoreDbContext.SaveChanges();
2019-05-15 14:56:09 +00:00
ClearCache(tenant);
}
private Tariff CalculateTariff(int tenantId, Tariff tariff)
{
tariff.State = TariffState.Paid;
2020-02-20 08:05:10 +00:00
var q = QuotaService.GetTenantQuota(tariff.QuotaId);
2019-05-15 14:56:09 +00:00
if (q == null || q.GetFeature("old"))
{
tariff.QuotaId = Tenant.DEFAULT_TENANT;
2020-02-20 08:05:10 +00:00
q = QuotaService.GetTenantQuota(tariff.QuotaId);
2019-05-15 14:56:09 +00:00
}
var delay = 0;
if (q != null && q.Trial)
{
tariff.State = TariffState.Trial;
if (tariff.DueDate == DateTime.MinValue || tariff.DueDate == DateTime.MaxValue)
{
2020-02-20 08:05:10 +00:00
var tenant = TenantService.GetTenant(tenantId);
2019-05-15 14:56:09 +00:00
if (tenant != null)
{
var fromDate = tenant.CreatedDateTime < tenant.VersionChanged ? tenant.VersionChanged : tenant.CreatedDateTime;
var trialPeriod = GetPeriod("TrialPeriod", DEFAULT_TRIAL_PERIOD);
if (fromDate == DateTime.MinValue) fromDate = DateTime.UtcNow.Date;
2019-08-15 13:00:20 +00:00
tariff.DueDate = trialPeriod != default ? fromDate.Date.AddDays(trialPeriod) : DateTime.MaxValue;
2019-05-15 14:56:09 +00:00
}
else
{
tariff.DueDate = DateTime.MaxValue;
}
}
}
else
{
2020-02-20 08:05:10 +00:00
delay = PaymentDelay;
2019-05-15 14:56:09 +00:00
}
if (tariff.DueDate != DateTime.MinValue && tariff.DueDate.Date < DateTime.Today && delay > 0)
{
tariff.State = TariffState.Delay;
tariff.DelayDueDate = tariff.DueDate.Date.AddDays(delay);
}
if (tariff.DueDate == DateTime.MinValue ||
tariff.DueDate != DateTime.MaxValue && tariff.DueDate.Date.AddDays(delay) < DateTime.Today)
{
tariff.State = TariffState.NotPaid;
if (CoreBaseSettings.Standalone)
{
if (q != null)
{
var defaultQuota = QuotaService.GetTenantQuota(Tenant.DEFAULT_TENANT);
defaultQuota.Name = "overdue";
defaultQuota.Features = q.Features;
defaultQuota.Support = false;
QuotaService.SaveTenantQuota(defaultQuota);
2019-05-15 14:56:09 +00:00
}
var unlimTariff = Tariff.CreateDefault();
unlimTariff.LicenseDate = tariff.DueDate;
tariff = unlimTariff;
}
}
tariff.Prolongable = tariff.DueDate == DateTime.MinValue || tariff.DueDate == DateTime.MaxValue ||
tariff.State == TariffState.Trial ||
new DateTime(tariff.DueDate.Year, tariff.DueDate.Month, 1) <= new DateTime(DateTime.UtcNow.Year, DateTime.UtcNow.Month, 1).AddMonths(1);
return tariff;
}
private int GetPeriod(string key, int defaultValue)
{
2020-02-20 08:05:10 +00:00
var settings = TenantService.GetTenantSettings(Tenant.DEFAULT_TENANT, key);
2019-05-15 14:56:09 +00:00
return settings != null ? Convert.ToInt32(Encoding.UTF8.GetString(settings)) : defaultValue;
}
private BillingClient GetBillingClient()
{
try
{
2021-05-17 11:35:00 +00:00
return new BillingClient(Test, Configuration);
2019-05-15 14:56:09 +00:00
}
catch (InvalidOperationException ioe)
{
throw new BillingNotConfiguredException(ioe.Message, ioe);
}
catch (ReflectionTypeLoadException rtle)
{
2020-02-20 08:05:10 +00:00
Log.ErrorFormat("{0}{1}LoaderExceptions: {2}",
2019-05-15 14:56:09 +00:00
rtle,
Environment.NewLine,
string.Join(Environment.NewLine, rtle.LoaderExceptions.Select(e => e.ToString())));
throw;
}
}
private string GetPortalId(int tenant)
{
2019-09-18 13:33:01 +00:00
return CoreSettings.GetKey(tenant);
2019-05-15 14:56:09 +00:00
}
private string GetAffiliateId(int tenant)
{
2019-09-18 13:33:01 +00:00
return CoreSettings.GetAffiliateId(tenant);
2020-02-17 08:58:14 +00:00
}
private string GetCampaign(int tenant)
{
return CoreSettings.GetCampaign(tenant);
}
2019-05-15 14:56:09 +00:00
private TimeSpan GetCacheExpiration()
{
2019-09-18 15:19:30 +00:00
if (CoreBaseSettings.Standalone && CacheExpiration < STANDALONE_CACHE_EXPIRATION)
2019-05-15 14:56:09 +00:00
{
CacheExpiration = CacheExpiration.Add(TimeSpan.FromSeconds(30));
}
return CacheExpiration;
}
private void ResetCacheExpiration()
{
2019-09-18 15:19:30 +00:00
if (CoreBaseSettings.Standalone)
2019-05-15 14:56:09 +00:00
{
CacheExpiration = DEFAULT_CACHE_EXPIRATION;
}
}
2021-05-17 11:35:00 +00:00
private void LogError(Exception error, string tenantId = null)
{
if (error is BillingNotFoundException)
{
Log.DebugFormat("Payment tenant {0} not found: {1}", tenantId, error.Message);
}
else if (error is BillingNotConfiguredException)
{
Log.DebugFormat("Billing tenant {0} not configured: {1}", tenantId, error.Message);
}
else
{
if (Log.IsDebugEnabled)
{
Log.Error("Billing tenant " + tenantId);
Log.Error(error);
}
else
{
Log.ErrorFormat("Billing tenant {0}: {1}", tenantId, error.Message);
}
}
2019-05-15 14:56:09 +00:00
}
2019-10-31 11:28:30 +00:00
}
2019-05-15 14:56:09 +00:00
}