Merge branch 'feature/stripe' of github.com:ONLYOFFICE/AppServer into feature/stripe

This commit is contained in:
Tatiana Lopaeva 2022-09-14 09:55:53 +03:00
commit 76a20ed0cf
21 changed files with 129 additions and 85 deletions

View File

@ -34,7 +34,7 @@ public class Tariff
public DateTime DueDate { get; set; }
public DateTime DelayDueDate { get; set; }
public DateTime LicenseDate { get; set; }
public Guid CustomerId { get; set; }
public string CustomerId { get; set; }
public List<Tuple<int, int>> Quotas { get; set; }
public static Tariff CreateDefault(bool empty = false)
@ -48,7 +48,7 @@ public class Tariff
DueDate = DateTime.MaxValue,
DelayDueDate = DateTime.MaxValue,
LicenseDate = DateTime.MaxValue,
CustomerId = Guid.Empty,
CustomerId = "",
Quotas = quotas
};
}

View File

@ -174,8 +174,7 @@ public class TariffService : ITariffService
if (!string.IsNullOrEmpty(email))
{
var customer = _userService.GetUser(tenantId, email);
asynctariff.CustomerId = customer != null && !customer.Removed ? customer.Id : Guid.Empty;
asynctariff.CustomerId = email;
}
if (SaveBillingInfo(tenantId, asynctariff))

View File

@ -31,7 +31,7 @@ public class DbTariff
public int Id { get; set; }
public int Tenant { get; set; }
public DateTime Stamp { get; set; }
public Guid CustomerId { get; set; }
public string CustomerId { get; set; }
public string Comment { get; set; }
public DateTime CreateOn { get; set; }
}
@ -73,7 +73,7 @@ public static class DbTariffExtension
entity.Property(e => e.CustomerId)
.HasColumnName("customer_id")
.HasColumnType("varchar(36)")
.HasColumnType("varchar(255)")
.HasCharSet("utf8")
.UseCollation("utf8_general_ci");
@ -104,7 +104,7 @@ public static class DbTariffExtension
entity.Property(e => e.CustomerId)
.HasColumnName("customer_id")
.HasMaxLength(36)
.HasMaxLength(255)
.HasDefaultValueSql("NULL");
entity.Property(e => e.Tenant).HasColumnName("tenant");

View File

@ -26,7 +26,7 @@
namespace ASC.Core.Common.Quota.Features;
internal class MaxFileSizeFeature : TenantQuotaFeatureLength
internal class MaxFileSizeFeature : TenantQuotaFeatureSize
{
public override string Name { get => "file_size"; }
public MaxFileSizeFeature(TenantQuota tenantQuota) : base(tenantQuota)

View File

@ -26,7 +26,7 @@
namespace ASC.Core.Common.Quota.Features;
public class MaxTotalSizeFeature : TenantQuotaFeatureLength
public class MaxTotalSizeFeature : TenantQuotaFeatureSize
{
public override string Name { get => "total_size"; }
public override bool Paid { get => true; }

View File

@ -0,0 +1,35 @@
// (c) Copyright Ascensio System SIA 2010-2022
//
// This program is a free software product.
// You can redistribute it and/or modify it under the terms
// of the GNU Affero General Public License (AGPL) version 3 as published by the Free Software
// Foundation. In accordance with Section 7(a) of the GNU AGPL 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 details, see
// the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
//
// You can contact Ascensio System SIA at Lubanas st. 125a-25, Riga, Latvia, EU, LV-1021.
//
// The interactive user interfaces in modified source and object code versions of the Program must
// display Appropriate Legal Notices, as required under Section 5 of the GNU AGPL version 3.
//
// Pursuant to Section 7(b) of the License you must retain the original Product logo when
// distributing the program. Pursuant to Section 7(e) we decline to grant you any rights under
// trademark law for use of our trademarks.
//
// All the Product's GUI elements, including illustrations and icon sets, as well as technical writing
// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
namespace ASC.Core.Common.Quota.Features;
public class UsersInRoomFeature : TenantQuotaFeatureCount
{
public override string Name { get => "usersInRoom"; }
public UsersInRoomFeature(TenantQuota tenantQuota) : base(tenantQuota)
{
}
}

View File

@ -103,11 +103,11 @@ public class TenantQuotaFeatureCount : TenantQuotaFeature<int>
}
}
public class TenantQuotaFeatureLength : TenantQuotaFeature<long>
public class TenantQuotaFeatureSize : TenantQuotaFeature<long>
{
protected override long Default => long.MaxValue;
public TenantQuotaFeatureLength(TenantQuota tenantQuota) : base(tenantQuota)
public TenantQuotaFeatureSize(TenantQuota tenantQuota) : base(tenantQuota)
{
}

View File

@ -97,6 +97,13 @@ public class TenantQuota : IMapFrom<DbQuota>
set => _countManagerFeature.Value = value;
}
private readonly UsersInRoomFeature _usersInRoomFeature;
public int UsersInRoom
{
get => _usersInRoomFeature.Value;
set => _usersInRoomFeature.Value = value;
}
private readonly CountRoomFeature _countRoomFeature;
public int CountRoom
{
@ -215,6 +222,7 @@ public class TenantQuota : IMapFrom<DbQuota>
_activeUsersFeature = new ActiveUsersFeature(this) { Order = 1 };
_countManagerFeature = new CountManagerFeature(this);
_usersInRoomFeature = new UsersInRoomFeature(this) { Order = 8 };
_countRoomFeature = new CountRoomFeature(this) { Order = 2 };
_maxTotalSizeFeature = new MaxTotalSizeFeature(this);
_maxFileSizeFeature = new MaxFileSizeFeature(this);
@ -238,6 +246,7 @@ public class TenantQuota : IMapFrom<DbQuota>
{
_activeUsersFeature,
_countManagerFeature,
_usersInRoomFeature,
_countRoomFeature,
_maxTotalSizeFeature,
_maxFileSizeFeature,
@ -328,11 +337,11 @@ public class TenantQuota : IMapFrom<DbQuota>
{
fileSize.Value = Math.Max(fileSize.Value, quota.MaxFileSize);
}
else if (f is TenantQuotaFeature<int> count)
else if (f is TenantQuotaFeatureCount count)
{
count.Value += quota.GetFeature<int>(f.Name).Value;
}
else if (f is TenantQuotaFeatureLength length)
else if (f is TenantQuotaFeatureSize length)
{
length.Value += quota.GetFeature<long>(f.Name).Value;
}

View File

@ -163,7 +163,7 @@ namespace ASC.Migrations.MySql.Migrations.CoreDb
b.Property<string>("CustomerId")
.IsRequired()
.HasColumnType("varchar(36)")
.HasColumnType("varchar(255)")
.HasColumnName("customer_id")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");

View File

@ -63,7 +63,8 @@ namespace ASC.Migrations.MySql.Migrations.CoreDb
migrationBuilder.AddColumn<string>(
name: "customer_id",
table: "tenants_tariff",
type: "varchar(36)",
type: "varchar(255)",
maxLength: 255,
nullable: false,
defaultValue: "",
collation: "utf8_general_ci")

View File

@ -152,7 +152,7 @@ namespace ASC.Migrations.MySql.Migrations
b.Property<string>("CustomerId")
.IsRequired()
.HasColumnType("varchar(36)")
.HasColumnType("varchar(255)")
.HasColumnName("customer_id")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");

View File

@ -162,8 +162,8 @@ namespace ASC.Migrations.PostgreSql.Migrations.CoreDb
b.Property<Guid>("CustomerId")
.ValueGeneratedOnAdd()
.HasMaxLength(36)
.HasColumnType("uuid")
.HasMaxLength(255)
.HasColumnType("character varying(255)")
.HasColumnName("customer_id")
.HasDefaultValueSql("NULL");

View File

@ -67,12 +67,12 @@ namespace ASC.Migrations.PostgreSql.Migrations.CoreDb
table: "tenants_quota",
newName: "product_id");
migrationBuilder.AddColumn<Guid>(
migrationBuilder.AddColumn<string>(
name: "customer_id",
schema: "onlyoffice",
table: "tenants_tariff",
type: "uuid",
maxLength: 36,
type: "character varying(255)",
maxLength: 255,
nullable: false,
defaultValueSql: "NULL");

View File

@ -151,8 +151,8 @@ namespace ASC.Migrations.PostgreSql.Migrations
b.Property<Guid>("CustomerId")
.ValueGeneratedOnAdd()
.HasMaxLength(36)
.HasColumnType("uuid")
.HasMaxLength(255)
.HasColumnType("character varying(255)")
.HasColumnName("customer_id")
.HasDefaultValueSql("NULL");

View File

@ -108,8 +108,9 @@ public class PaymentController : ControllerBase
public Uri GetPaymentAccount(string backUrl)
{
var payerId = _tariffService.GetTariff(Tenant.Id).CustomerId;
var payer = _userManager.GetUserByEmail(payerId);
if (_securityContext.CurrentAccount.ID != payerId &&
if (_securityContext.CurrentAccount.ID != payer.Id &&
_securityContext.CurrentAccount.ID != Tenant.OwnerId)
{
return null;

View File

@ -724,7 +724,12 @@ public class SettingsController : BaseSettingsController
{
var settings = _settingsManager.LoadForDefaultTenant<AdditionalWhiteLabelSettings>();
var currentQuota = _tenantExtra.GetTenantQuota();
var currentTariff = _tenantExtra.GetCurrentTariff();
var currentTariff = _tenantExtra.GetCurrentTariff();
if (!int.TryParse(_configuration["core:payment:max-quantity"], out var maxQuotaQuantity))
{
maxQuotaQuantity = 999;
}
return
new
@ -737,7 +742,8 @@ public class SettingsController : BaseSettingsController
{
currentQuota.Trial,
currentTariff.DueDate.Date
}
},
max = maxQuotaQuantity
};
}

View File

@ -37,19 +37,20 @@ public class QuotaDto
public bool Free { get; set; }
public bool Trial { get; set; }
public IAsyncEnumerable<QuotaFeatureDto> Features { get; set; }
public IAsyncEnumerable<TenantQuotaFeatureDto> Features { get; set; }
}
public class QuotaFeatureDto : IEquatable<QuotaFeatureDto>
public class TenantQuotaFeatureDto : IEquatable<TenantQuotaFeatureDto>
{
public string Id { get; set; }
public string Title { get; set; }
public string Image { get; set; }
public object Value { get; set; }
public string Type { get; set; }
public FeatureUsedDto Used { get; set; }
public FeaturePriceDto Price { get; set; }
public string PriceTitle { get; set; }
public bool Equals(QuotaFeatureDto other)
public bool Equals(TenantQuotaFeatureDto other)
{
if (other is null)
{
@ -59,7 +60,7 @@ public class QuotaFeatureDto : IEquatable<QuotaFeatureDto>
return Id == other.Id;
}
public override bool Equals(object obj) => Equals(obj as QuotaFeatureDto);
public override bool Equals(object obj) => Equals(obj as TenantQuotaFeatureDto);
public override int GetHashCode() => Id.GetHashCode();
}
@ -69,12 +70,6 @@ public class PriceDto
public string CurrencySymbol { get; set; }
}
public class FeaturePriceDto
{
public string Count { get; set; }
public string Per { get; set; }
}
public class FeatureUsedDto
{
public object Value { get; set; }

View File

@ -61,7 +61,7 @@ public class QuotaHelper
private QuotaDto ToQuotaDto(TenantQuota quota, IDictionary<string, Dictionary<string, decimal>> priceInfo, RegionInfo currentRegion, bool getUsed = false)
{
var price = GetPrice(quota, priceInfo, currentRegion);
var features = GetFeatures(quota, GetPriceString(price, currentRegion), getUsed);
var features = GetFeatures(quota, getUsed);
return new QuotaDto
{
@ -95,18 +95,7 @@ public class QuotaHelper
return quota.Price;
}
private string GetPriceString(decimal price, RegionInfo currentRegion)
{
var inEuro = "EUR".Equals(currentRegion.ISOCurrencySymbol);
var priceString = inEuro && Math.Truncate(price) != price ?
price.ToString(CultureInfo.InvariantCulture) :
((int)price).ToString(CultureInfo.InvariantCulture);
return string.Format("{0}{1}", currentRegion.CurrencySymbol, priceString);
}
private async IAsyncEnumerable<QuotaFeatureDto> GetFeatures(TenantQuota quota, string price, bool getUsed)
private async IAsyncEnumerable<TenantQuotaFeatureDto> GetFeatures(TenantQuota quota, bool getUsed)
{
var assembly = GetType().Assembly;
@ -114,38 +103,35 @@ public class QuotaHelper
foreach (var feature in quota.TenantQuotaFeatures.Where(r => r.Visible).OrderBy(r => r.Order))
{
var result = new QuotaFeatureDto();
var result = new TenantQuotaFeatureDto();
if (feature.Paid)
{
result.Price = new FeaturePriceDto
{
Per = string.Format(Resource.ResourceManager.GetString($"TariffsFeature_{feature.Name}_price_per"), price),
Count = Resource.ResourceManager.GetString($"TariffsFeature_{feature.Name}_price_count")
};
result.PriceTitle = Resource.ResourceManager.GetString($"TariffsFeature_{feature.Name}_price_count");
}
result.Id = feature.Name;
object used = null;
if (feature is TenantQuotaFeature<long> length)
if (feature is TenantQuotaFeatureSize size)
{
var maxValue = length.Value == long.MaxValue;
result.Value = maxValue ? -1 : length.Value;
result.Value = size.Value == long.MaxValue ? -1 : size.Value;
result.Type = "size";
await GetStat<long>();
}
else if (feature is TenantQuotaFeature<int> count)
else if (feature is TenantQuotaFeatureCount count)
{
var maxValue = count.Value == int.MaxValue;
result.Value = maxValue ? -1 : count.Value;
result.Value = count.Value == int.MaxValue ? -1 : count.Value;
result.Type = "count";
await GetStat<int>();
}
else if (feature is TenantQuotaFeature<bool> flag)
else if (feature is TenantQuotaFeatureFlag flag)
{
result.Value = flag.Value;
result.Type = "flag";
}
if (getUsed)

View File

@ -2184,15 +2184,6 @@ namespace ASC.Web.Core.PublicResources {
}
}
/// <summary>
/// Looks up a localized string similar to {0} per manager/month.
/// </summary>
public static string TariffsFeature_manager_price_per {
get {
return ResourceManager.GetString("TariffsFeature_manager_price_per", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Automatic backup &amp; recovery.
/// </summary>
@ -2239,11 +2230,20 @@ namespace ASC.Web.Core.PublicResources {
}
/// <summary>
/// Looks up a localized string similar to .
/// Looks up a localized string similar to Managers added:.
/// </summary>
public static string TariffsFeature_total_size_price_per {
public static string TariffsFeature_used_manager {
get {
return ResourceManager.GetString("TariffsFeature_total_size_price_per", resourceCulture);
return ResourceManager.GetString("TariffsFeature_used_manager", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Room:.
/// </summary>
public static string TariffsFeature_used_room {
get {
return ResourceManager.GetString("TariffsFeature_used_room", resourceCulture);
}
}
@ -2257,11 +2257,11 @@ namespace ASC.Web.Core.PublicResources {
}
/// <summary>
/// Looks up a localized string similar to Managers added:.
/// Looks up a localized string similar to Users in room:.
/// </summary>
public static string TariffsFeature_used_users {
public static string TariffsFeature_used_usersInRoom {
get {
return ResourceManager.GetString("TariffsFeature_used_users", resourceCulture);
return ResourceManager.GetString("TariffsFeature_used_usersInRoom", resourceCulture);
}
}
@ -2274,6 +2274,15 @@ namespace ASC.Web.Core.PublicResources {
}
}
/// <summary>
/// Looks up a localized string similar to Users in room.
/// </summary>
public static string TariffsFeature_usersInRoom {
get {
return ResourceManager.GetString("TariffsFeature_usersInRoom", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Branding &amp; customization.
/// </summary>

View File

@ -828,9 +828,6 @@
<data name="TariffsFeature_manager_price_count" xml:space="preserve">
<value>Number of managers</value>
</data>
<data name="TariffsFeature_manager_price_per" xml:space="preserve">
<value>{0} per manager/month</value>
</data>
<data name="TariffsFeature_audit" xml:space="preserve">
<value>Tracking user logins &amp; action</value>
</data>
@ -858,7 +855,7 @@
<data name="TariffsFeature_used_total_size" xml:space="preserve">
<value>Storage space used:</value>
</data>
<data name="TariffsFeature_used_users" xml:space="preserve">
<data name="TariffsFeature_used_manager" xml:space="preserve">
<value>Managers added:</value>
</data>
<data name="Tariffs_startup" xml:space="preserve">
@ -867,10 +864,16 @@
<data name="TariffsFeature_total_size_price_count" xml:space="preserve">
<value>Storage space</value>
</data>
<data name="TariffsFeature_total_size_price_per" xml:space="preserve">
<value />
</data>
<data name="TariffsFeature_file_size" xml:space="preserve">
<value>Max file size</value>
</data>
<data name="TariffsFeature_used_room" xml:space="preserve">
<value>Room:</value>
</data>
<data name="TariffsFeature_used_usersInRoom" xml:space="preserve">
<value>Users in room:</value>
</data>
<data name="TariffsFeature_usersInRoom" xml:space="preserve">
<value>Users in room</value>
</data>
</root>