Merge pull request #727 from ONLYOFFICE/feature/remove-voip

Feature/remove voip
This commit is contained in:
Pavel Bannov 2022-07-18 12:32:50 +03:00 committed by GitHub
commit 5f5b1f80c3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
58 changed files with 279 additions and 8106 deletions

View File

@ -24,8 +24,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ASC.FederatedLogin", "commo
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ASC.Web.Core", "web\ASC.Web.Core\ASC.Web.Core.csproj", "{02C40A64-FE22-41D0-9037-69F0D6F787A9}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ASC.VoipService", "common\ASC.VoipService\ASC.VoipService.csproj", "{988536C1-4B89-4649-8F77-5C16F55D95D1}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ASC.MessagingSystem", "common\ASC.MessagingSystem\ASC.MessagingSystem.csproj", "{BD8A18A5-60C5-4411-9719-0AA11B4BE0E9}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ASC.IPSecurity", "common\ASC.IPSecurity\ASC.IPSecurity.csproj", "{2FF2177F-2D1A-4396-84EB-51F14FD99385}"
@ -147,10 +145,6 @@ Global
{02C40A64-FE22-41D0-9037-69F0D6F787A9}.Debug|Any CPU.Build.0 = Debug|Any CPU
{02C40A64-FE22-41D0-9037-69F0D6F787A9}.Release|Any CPU.ActiveCfg = Release|Any CPU
{02C40A64-FE22-41D0-9037-69F0D6F787A9}.Release|Any CPU.Build.0 = Release|Any CPU
{988536C1-4B89-4649-8F77-5C16F55D95D1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{988536C1-4B89-4649-8F77-5C16F55D95D1}.Debug|Any CPU.Build.0 = Debug|Any CPU
{988536C1-4B89-4649-8F77-5C16F55D95D1}.Release|Any CPU.ActiveCfg = Release|Any CPU
{988536C1-4B89-4649-8F77-5C16F55D95D1}.Release|Any CPU.Build.0 = Release|Any CPU
{BD8A18A5-60C5-4411-9719-0AA11B4BE0E9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{BD8A18A5-60C5-4411-9719-0AA11B4BE0E9}.Debug|Any CPU.Build.0 = Debug|Any CPU
{BD8A18A5-60C5-4411-9719-0AA11B4BE0E9}.Release|Any CPU.ActiveCfg = Release|Any CPU

View File

@ -20,7 +20,6 @@
"common\\ASC.Migration\\ASC.Migration.csproj",
"common\\ASC.Notify.Textile\\ASC.Notify.Textile.csproj",
"common\\ASC.Textile\\ASC.Textile.csproj",
"common\\ASC.VoipService\\ASC.VoipService.csproj",
"common\\ASC.Webhooks.Core\\ASC.Webhooks.Core.csproj",
"common\\services\\ASC.AuditTrail\\ASC.AuditTrail.csproj",
"common\\services\\ASC.ClearEvents\\ASC.ClearEvents.csproj",

View File

@ -1,65 +0,0 @@
// (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.EF.Context;
public class MySqlVoipDbContext : VoipDbContext { }
public class PostgreSqlVoipDbContext : VoipDbContext { }
public class VoipDbContext : BaseDbContext
{
public DbSet<VoipNumber> VoipNumbers { get; set; }
public DbSet<DbVoipCall> VoipCalls { get; set; }
public DbSet<CrmContact> CrmContact { get; set; }
protected override Dictionary<Provider, Func<BaseDbContext>> ProviderContext
{
get
{
return new Dictionary<Provider, Func<BaseDbContext>>()
{
{ Provider.MySql, () => new MySqlVoipDbContext() } ,
{ Provider.PostgreSql, () => new PostgreSqlVoipDbContext() } ,
};
}
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
ModelBuilderWrapper
.From(modelBuilder, _provider)
.AddVoipNumber()
.AddDbVoipCall()
.AddCrmContact();
}
}
public static class VoipDbExtension
{
public static DIHelper AddVoipDbContextService(this DIHelper services)
{
return services.AddDbContextManagerService<VoipDbContext>();
}
}

View File

@ -1,208 +0,0 @@
// (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.EF.Model;
public class DbVoipCall
{
public string Id { get; set; }
public string ParentCallId { get; set; }
public string NumberFrom { get; set; }
public string NumberTo { get; set; }
public int Status { get; set; }
public Guid AnsweredBy { get; set; }
public DateTime DialDate { get; set; }
public int DialDuration { get; set; }
public string Sid { get; set; }
public string Uri { get; set; }
public int Duration { get; set; }
public decimal RecordPrice { get; set; }
public int ContactId { get; set; }
public decimal Price { get; set; }
public int TenantId { get; set; }
public CrmContact CrmContact { get; set; }
}
public static class DbVoipCallExtension
{
public static ModelBuilderWrapper AddDbVoipCall(this ModelBuilderWrapper modelBuilder)
{
modelBuilder
.Add(MySqlAddDbVoipCall, Provider.MySql)
.Add(PgSqlAddDbVoipCall, Provider.PostgreSql);
return modelBuilder;
}
public static void MySqlAddDbVoipCall(this ModelBuilder modelBuilder)
{
modelBuilder.Entity<DbVoipCall>(entity =>
{
entity.ToTable("crm_voip_calls");
entity.HasIndex(e => e.TenantId)
.HasDatabaseName("tenant_id");
entity.HasIndex(e => new { e.ParentCallId, e.TenantId })
.HasDatabaseName("parent_call_id");
entity.Property(e => e.Id)
.HasColumnName("id")
.HasColumnType("varchar(50)")
.HasCharSet("utf8")
.UseCollation("utf8_general_ci");
entity.Property(e => e.AnsweredBy)
.IsRequired()
.HasColumnName("answered_by")
.HasColumnType("varchar(50)")
.HasDefaultValueSql("'00000000-0000-0000-0000-000000000000'")
.HasCharSet("utf8")
.UseCollation("utf8_general_ci");
entity.Property(e => e.ContactId).HasColumnName("contact_id");
entity.Property(e => e.DialDate)
.HasColumnName("dial_date")
.HasColumnType("datetime");
entity.Property(e => e.DialDuration).HasColumnName("dial_duration");
entity.Property(e => e.NumberFrom)
.IsRequired()
.HasColumnName("number_from")
.HasColumnType("varchar(50)")
.HasCharSet("utf8")
.UseCollation("utf8_general_ci");
entity.Property(e => e.NumberTo)
.IsRequired()
.HasColumnName("number_to")
.HasColumnType("varchar(50)")
.HasCharSet("utf8")
.UseCollation("utf8_general_ci");
entity.Property(e => e.ParentCallId)
.IsRequired()
.HasColumnName("parent_call_id")
.HasColumnType("varchar(50)")
.HasCharSet("utf8")
.UseCollation("utf8_general_ci");
entity.Property(e => e.Price)
.HasColumnName("price")
.HasColumnType("decimal(10,4)");
entity.Property(e => e.Duration).HasColumnName("record_duration");
entity.Property(e => e.RecordPrice)
.HasColumnName("record_price")
.HasColumnType("decimal(10,4)");
entity.Property(e => e.Sid)
.HasColumnName("record_sid")
.HasColumnType("varchar(50)")
.HasCharSet("utf8")
.UseCollation("utf8_general_ci");
entity.Property(e => e.Uri)
.HasColumnName("record_url")
.HasColumnType("text")
.HasCharSet("utf8")
.UseCollation("utf8_general_ci");
entity.Property(e => e.Status).HasColumnName("status");
entity.Property(e => e.TenantId).HasColumnName("tenant_id");
});
}
public static void PgSqlAddDbVoipCall(this ModelBuilder modelBuilder)
{
modelBuilder.Entity<DbVoipCall>(entity =>
{
entity.ToTable("crm_voip_calls", "onlyoffice");
entity.HasIndex(e => e.TenantId)
.HasDatabaseName("tenant_id_crm_voip_calls");
entity.HasIndex(e => new { e.ParentCallId, e.TenantId })
.HasDatabaseName("parent_call_id");
entity.Property(e => e.Id)
.HasColumnName("id")
.HasMaxLength(50);
entity.Property(e => e.AnsweredBy)
.IsRequired()
.HasColumnName("answered_by")
.HasMaxLength(50)
.HasDefaultValueSql("'00000000-0000-0000-0000-000000000000'");
entity.Property(e => e.ContactId).HasColumnName("contact_id");
entity.Property(e => e.DialDate).HasColumnName("dial_date");
entity.Property(e => e.DialDuration).HasColumnName("dial_duration");
entity.Property(e => e.NumberFrom)
.IsRequired()
.HasColumnName("number_from")
.HasMaxLength(50);
entity.Property(e => e.NumberTo)
.IsRequired()
.HasColumnName("number_to")
.HasMaxLength(50);
entity.Property(e => e.ParentCallId)
.IsRequired()
.HasColumnName("parent_call_id")
.HasMaxLength(50);
entity.Property(e => e.Price)
.HasColumnName("price")
.HasColumnType("numeric(10,4)")
.HasDefaultValueSql("NULL");
entity.Property(e => e.Duration).HasColumnName("record_duration");
entity.Property(e => e.RecordPrice)
.HasColumnName("record_price")
.HasColumnType("numeric(10,4)");
entity.Property(e => e.Sid)
.HasColumnName("record_sid")
.HasMaxLength(50)
.HasDefaultValueSql("NULL");
entity.Property(e => e.Uri).HasColumnName("record_url");
entity.Property(e => e.Status).HasColumnName("status");
entity.Property(e => e.TenantId).HasColumnName("tenant_id");
});
}
}

View File

@ -1,112 +0,0 @@
// (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.EF.Model;
public class VoipNumber
{
public string Id { get; set; }
public string Number { get; set; }
public string Alias { get; set; }
public string Settings { get; set; }
public int TenantId { get; set; }
}
public static class VoipNumberExtension
{
public static ModelBuilderWrapper AddVoipNumber(this ModelBuilderWrapper modelBuilder)
{
modelBuilder
.Add(MySqlAddVoipNumber, Provider.MySql)
.Add(PgSqlAddVoipNumber, Provider.PostgreSql);
return modelBuilder;
}
public static void MySqlAddVoipNumber(this ModelBuilder modelBuilder)
{
modelBuilder.Entity<VoipNumber>(entity =>
{
entity.ToTable("crm_voip_number");
entity.HasIndex(e => e.TenantId)
.HasDatabaseName("tenant_id");
entity.Property(e => e.Id)
.HasColumnName("id")
.HasColumnType("varchar(50)")
.HasCharSet("utf8")
.UseCollation("utf8_general_ci");
entity.Property(e => e.Alias)
.HasColumnName("alias")
.HasColumnType("varchar(255)")
.HasCharSet("utf8")
.UseCollation("utf8_general_ci");
entity.Property(e => e.Number)
.IsRequired()
.HasColumnName("number")
.HasColumnType("varchar(50)")
.HasCharSet("utf8")
.UseCollation("utf8_general_ci");
entity.Property(e => e.Settings)
.HasColumnName("settings")
.HasColumnType("text")
.HasCharSet("utf8")
.UseCollation("utf8_general_ci");
entity.Property(e => e.TenantId).HasColumnName("tenant_id");
});
}
public static void PgSqlAddVoipNumber(this ModelBuilder modelBuilder)
{
modelBuilder.Entity<VoipNumber>(entity =>
{
entity.ToTable("crm_voip_number", "onlyoffice");
entity.HasIndex(e => e.TenantId)
.HasDatabaseName("tenant_id_crm_voip_number");
entity.Property(e => e.Id)
.HasColumnName("id")
.HasMaxLength(50);
entity.Property(e => e.Alias)
.HasColumnName("alias")
.HasMaxLength(255)
.HasDefaultValueSql("NULL");
entity.Property(e => e.Number)
.IsRequired()
.HasColumnName("number")
.HasMaxLength(50);
entity.Property(e => e.Settings).HasColumnName("settings");
entity.Property(e => e.TenantId).HasColumnName("tenant_id");
});
}
}

View File

@ -1,282 +0,0 @@
// <auto-generated />
namespace ASC.Core.Common.Migrations.MySql.VoipDbContextMySql
{
[DbContext(typeof(MySqlVoipDbContext))]
[Migration("20211012145344_VoipDbContextMySql")]
partial class VoipDbContextMySql
{
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("Relational:MaxIdentifierLength", 64)
.HasAnnotation("ProductVersion", "5.0.10");
modelBuilder.Entity("ASC.Core.Common.EF.Model.CrmContact", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int")
.HasColumnName("id");
b.Property<int>("CompanyId")
.HasColumnType("int")
.HasColumnName("company_id");
b.Property<string>("CompanyName")
.HasColumnType("varchar(255)")
.HasColumnName("company_name")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<int>("ContactTypeId")
.HasColumnType("int")
.HasColumnName("contact_type_id");
b.Property<string>("CreateBy")
.IsRequired()
.HasColumnType("char(38)")
.HasColumnName("create_by")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<DateTime>("CreateOn")
.HasColumnType("datetime")
.HasColumnName("create_on");
b.Property<string>("Currency")
.HasColumnType("varchar(3)")
.HasColumnName("currency")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<string>("DisplayName")
.HasColumnType("varchar(255)")
.HasColumnName("display_name")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<string>("FirstName")
.HasColumnType("varchar(255)")
.HasColumnName("first_name")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<string>("Industry")
.HasColumnType("varchar(255)")
.HasColumnName("industry")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<bool>("IsCompany")
.HasColumnType("tinyint(1)")
.HasColumnName("is_company");
b.Property<bool>("IsShared")
.HasColumnType("tinyint(1)")
.HasColumnName("is_shared");
b.Property<string>("LastModifedBy")
.IsRequired()
.HasColumnType("char(38)")
.HasColumnName("last_modifed_by")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<DateTime>("LastModifedOn")
.HasColumnType("datetime")
.HasColumnName("last_modifed_on");
b.Property<string>("LastName")
.HasColumnType("varchar(255)")
.HasColumnName("last_name")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<string>("Notes")
.HasColumnType("text")
.HasColumnName("notes")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<int>("StatusId")
.HasColumnType("int")
.HasColumnName("status_id");
b.Property<int>("TenantId")
.HasColumnType("int")
.HasColumnName("tenant_id");
b.Property<string>("Title")
.HasColumnType("varchar(255)")
.HasColumnName("title")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.HasKey("Id");
b.HasIndex("CreateOn")
.HasDatabaseName("create_on");
b.HasIndex("LastModifedOn", "TenantId")
.HasDatabaseName("last_modifed_on");
b.HasIndex("TenantId", "CompanyId")
.HasDatabaseName("company_id");
b.HasIndex("TenantId", "DisplayName")
.HasDatabaseName("display_name");
b.ToTable("crm_contact");
});
modelBuilder.Entity("ASC.Core.Common.EF.Model.DbVoipCall", b =>
{
b.Property<string>("Id")
.HasColumnType("varchar(50)")
.HasColumnName("id")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<string>("AnsweredBy")
.IsRequired()
.ValueGeneratedOnAdd()
.HasColumnType("varchar(50)")
.HasColumnName("answered_by")
.HasDefaultValueSql("'00000000-0000-0000-0000-000000000000'")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<int>("ContactId")
.HasColumnType("int")
.HasColumnName("contact_id");
b.Property<int?>("CrmContactId")
.HasColumnType("int");
b.Property<DateTime>("DialDate")
.HasColumnType("datetime")
.HasColumnName("dial_date");
b.Property<int>("DialDuration")
.HasColumnType("int")
.HasColumnName("dial_duration");
b.Property<string>("NumberFrom")
.IsRequired()
.HasColumnType("varchar(50)")
.HasColumnName("number_from")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<string>("NumberTo")
.IsRequired()
.HasColumnType("varchar(50)")
.HasColumnName("number_to")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<string>("ParentCallId")
.IsRequired()
.HasColumnType("varchar(50)")
.HasColumnName("parent_call_id")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<decimal>("Price")
.HasColumnType("decimal(10,4)")
.HasColumnName("price");
b.Property<int>("RecordDuration")
.HasColumnType("int")
.HasColumnName("record_duration");
b.Property<decimal>("RecordPrice")
.HasColumnType("decimal(10,4)")
.HasColumnName("record_price");
b.Property<string>("RecordSid")
.HasColumnType("varchar(50)")
.HasColumnName("record_sid")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<string>("RecordUrl")
.HasColumnType("text")
.HasColumnName("record_url")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<int>("Status")
.HasColumnType("int")
.HasColumnName("status");
b.Property<int>("TenantId")
.HasColumnType("int")
.HasColumnName("tenant_id");
b.HasKey("Id");
b.HasIndex("CrmContactId");
b.HasIndex("TenantId")
.HasDatabaseName("tenant_id");
b.HasIndex("ParentCallId", "TenantId")
.HasDatabaseName("parent_call_id");
b.ToTable("crm_voip_calls");
});
modelBuilder.Entity("ASC.Core.Common.EF.Model.VoipNumber", b =>
{
b.Property<string>("Id")
.HasColumnType("varchar(50)")
.HasColumnName("id")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<string>("Alias")
.HasColumnType("varchar(255)")
.HasColumnName("alias")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<string>("Number")
.IsRequired()
.HasColumnType("varchar(50)")
.HasColumnName("number")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<string>("Settings")
.HasColumnType("text")
.HasColumnName("settings")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<int>("TenantId")
.HasColumnType("int")
.HasColumnName("tenant_id");
b.HasKey("Id");
b.HasIndex("TenantId")
.HasDatabaseName("tenant_id");
b.ToTable("crm_voip_number");
});
modelBuilder.Entity("ASC.Core.Common.EF.Model.DbVoipCall", b =>
{
b.HasOne("ASC.Core.Common.EF.Model.CrmContact", "CrmContact")
.WithMany()
.HasForeignKey("CrmContactId");
b.Navigation("CrmContact");
});
#pragma warning restore 612, 618
}
}
}

View File

@ -1,189 +0,0 @@
// (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.Migrations.MySql.VoipDbContextMySql;
public partial class VoipDbContextMySql : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AlterDatabase()
.Annotation("MySql:CharSet", "utf8mb4");
migrationBuilder.CreateTable(
name: "crm_contact",
columns: table => new
{
id = table.Column<int>(type: "int", nullable: false)
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
tenant_id = table.Column<int>(type: "int", nullable: false),
is_company = table.Column<bool>(type: "tinyint(1)", nullable: false),
notes = table.Column<string>(type: "text", nullable: true, collation: "utf8_general_ci")
.Annotation("MySql:CharSet", "utf8"),
title = table.Column<string>(type: "varchar(255)", nullable: true, collation: "utf8_general_ci")
.Annotation("MySql:CharSet", "utf8"),
first_name = table.Column<string>(type: "varchar(255)", nullable: true, collation: "utf8_general_ci")
.Annotation("MySql:CharSet", "utf8"),
last_name = table.Column<string>(type: "varchar(255)", nullable: true, collation: "utf8_general_ci")
.Annotation("MySql:CharSet", "utf8"),
company_name = table.Column<string>(type: "varchar(255)", nullable: true, collation: "utf8_general_ci")
.Annotation("MySql:CharSet", "utf8"),
industry = table.Column<string>(type: "varchar(255)", nullable: true, collation: "utf8_general_ci")
.Annotation("MySql:CharSet", "utf8"),
status_id = table.Column<int>(type: "int", nullable: false),
company_id = table.Column<int>(type: "int", nullable: false),
contact_type_id = table.Column<int>(type: "int", nullable: false),
create_by = table.Column<string>(type: "char(38)", nullable: false, collation: "utf8_general_ci")
.Annotation("MySql:CharSet", "utf8"),
create_on = table.Column<DateTime>(type: "datetime", nullable: false),
last_modifed_by = table.Column<string>(type: "char(38)", nullable: false, collation: "utf8_general_ci")
.Annotation("MySql:CharSet", "utf8"),
last_modifed_on = table.Column<DateTime>(type: "datetime", nullable: false),
display_name = table.Column<string>(type: "varchar(255)", nullable: true, collation: "utf8_general_ci")
.Annotation("MySql:CharSet", "utf8"),
is_shared = table.Column<bool>(type: "tinyint(1)", nullable: false),
currency = table.Column<string>(type: "varchar(3)", nullable: true, collation: "utf8_general_ci")
.Annotation("MySql:CharSet", "utf8")
},
constraints: table =>
{
table.PrimaryKey("PK_crm_contact", x => x.id);
})
.Annotation("MySql:CharSet", "utf8mb4");
migrationBuilder.CreateTable(
name: "crm_voip_number",
columns: table => new
{
id = table.Column<string>(type: "varchar(50)", nullable: false, collation: "utf8_general_ci")
.Annotation("MySql:CharSet", "utf8"),
number = table.Column<string>(type: "varchar(50)", nullable: false, collation: "utf8_general_ci")
.Annotation("MySql:CharSet", "utf8"),
alias = table.Column<string>(type: "varchar(255)", nullable: true, collation: "utf8_general_ci")
.Annotation("MySql:CharSet", "utf8"),
settings = table.Column<string>(type: "text", nullable: true, collation: "utf8_general_ci")
.Annotation("MySql:CharSet", "utf8"),
tenant_id = table.Column<int>(type: "int", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_crm_voip_number", x => x.id);
})
.Annotation("MySql:CharSet", "utf8mb4");
migrationBuilder.CreateTable(
name: "crm_voip_calls",
columns: table => new
{
id = table.Column<string>(type: "varchar(50)", nullable: false, collation: "utf8_general_ci")
.Annotation("MySql:CharSet", "utf8"),
parent_call_id = table.Column<string>(type: "varchar(50)", nullable: false, collation: "utf8_general_ci")
.Annotation("MySql:CharSet", "utf8"),
number_from = table.Column<string>(type: "varchar(50)", nullable: false, collation: "utf8_general_ci")
.Annotation("MySql:CharSet", "utf8"),
number_to = table.Column<string>(type: "varchar(50)", nullable: false, collation: "utf8_general_ci")
.Annotation("MySql:CharSet", "utf8"),
status = table.Column<int>(type: "int", nullable: false),
answered_by = table.Column<string>(type: "varchar(50)", nullable: false, defaultValueSql: "'00000000-0000-0000-0000-000000000000'", collation: "utf8_general_ci")
.Annotation("MySql:CharSet", "utf8"),
dial_date = table.Column<DateTime>(type: "datetime", nullable: false),
dial_duration = table.Column<int>(type: "int", nullable: false),
record_sid = table.Column<string>(type: "varchar(50)", nullable: true, collation: "utf8_general_ci")
.Annotation("MySql:CharSet", "utf8"),
record_url = table.Column<string>(type: "text", nullable: true, collation: "utf8_general_ci")
.Annotation("MySql:CharSet", "utf8"),
record_duration = table.Column<int>(type: "int", nullable: false),
record_price = table.Column<decimal>(type: "decimal(10,4)", nullable: false),
contact_id = table.Column<int>(type: "int", nullable: false),
price = table.Column<decimal>(type: "decimal(10,4)", nullable: false),
tenant_id = table.Column<int>(type: "int", nullable: false),
CrmContactId = table.Column<int>(type: "int", nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_crm_voip_calls", x => x.id);
table.ForeignKey(
name: "FK_crm_voip_calls_crm_contact_CrmContactId",
column: x => x.CrmContactId,
principalTable: "crm_contact",
principalColumn: "id",
onDelete: ReferentialAction.Restrict);
})
.Annotation("MySql:CharSet", "utf8mb4");
migrationBuilder.CreateIndex(
name: "company_id",
table: "crm_contact",
columns: new[] { "tenant_id", "company_id" });
migrationBuilder.CreateIndex(
name: "create_on",
table: "crm_contact",
column: "create_on");
migrationBuilder.CreateIndex(
name: "display_name",
table: "crm_contact",
columns: new[] { "tenant_id", "display_name" });
migrationBuilder.CreateIndex(
name: "last_modifed_on",
table: "crm_contact",
columns: new[] { "last_modifed_on", "tenant_id" });
migrationBuilder.CreateIndex(
name: "IX_crm_voip_calls_CrmContactId",
table: "crm_voip_calls",
column: "CrmContactId");
migrationBuilder.CreateIndex(
name: "parent_call_id",
table: "crm_voip_calls",
columns: new[] { "parent_call_id", "tenant_id" });
migrationBuilder.CreateIndex(
name: "tenant_id",
table: "crm_voip_calls",
column: "tenant_id");
migrationBuilder.CreateIndex(
name: "tenant_id",
table: "crm_voip_number",
column: "tenant_id");
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "crm_voip_calls");
migrationBuilder.DropTable(
name: "crm_voip_number");
migrationBuilder.DropTable(
name: "crm_contact");
}
}

View File

@ -1,281 +0,0 @@
// <auto-generated />
namespace ASC.Core.Common.Migrations.MySql.VoipDbContextMySql
{
[DbContext(typeof(MySqlVoipDbContext))]
partial class MySqlVoipDbContextModelSnapshot : ModelSnapshot
{
protected override void BuildModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("Relational:MaxIdentifierLength", 64)
.HasAnnotation("ProductVersion", "5.0.10");
modelBuilder.Entity("ASC.Core.Common.EF.Model.CrmContact", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int")
.HasColumnName("id");
b.Property<int>("CompanyId")
.HasColumnType("int")
.HasColumnName("company_id");
b.Property<string>("CompanyName")
.HasColumnType("varchar(255)")
.HasColumnName("company_name")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<int>("ContactTypeId")
.HasColumnType("int")
.HasColumnName("contact_type_id");
b.Property<string>("CreateBy")
.IsRequired()
.HasColumnType("char(38)")
.HasColumnName("create_by")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<DateTime>("CreateOn")
.HasColumnType("datetime")
.HasColumnName("create_on");
b.Property<string>("Currency")
.HasColumnType("varchar(3)")
.HasColumnName("currency")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<string>("DisplayName")
.HasColumnType("varchar(255)")
.HasColumnName("display_name")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<string>("FirstName")
.HasColumnType("varchar(255)")
.HasColumnName("first_name")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<string>("Industry")
.HasColumnType("varchar(255)")
.HasColumnName("industry")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<bool>("IsCompany")
.HasColumnType("tinyint(1)")
.HasColumnName("is_company");
b.Property<bool>("IsShared")
.HasColumnType("tinyint(1)")
.HasColumnName("is_shared");
b.Property<string>("LastModifedBy")
.IsRequired()
.HasColumnType("char(38)")
.HasColumnName("last_modifed_by")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<DateTime>("LastModifedOn")
.HasColumnType("datetime")
.HasColumnName("last_modifed_on");
b.Property<string>("LastName")
.HasColumnType("varchar(255)")
.HasColumnName("last_name")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<string>("Notes")
.HasColumnType("text")
.HasColumnName("notes")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<int>("StatusId")
.HasColumnType("int")
.HasColumnName("status_id");
b.Property<int>("TenantId")
.HasColumnType("int")
.HasColumnName("tenant_id");
b.Property<string>("Title")
.HasColumnType("varchar(255)")
.HasColumnName("title")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.HasKey("Id");
b.HasIndex("CreateOn")
.HasDatabaseName("create_on");
b.HasIndex("LastModifedOn", "TenantId")
.HasDatabaseName("last_modifed_on");
b.HasIndex("TenantId", "CompanyId")
.HasDatabaseName("company_id");
b.HasIndex("TenantId", "DisplayName")
.HasDatabaseName("display_name");
b.ToTable("crm_contact");
});
modelBuilder.Entity("ASC.Core.Common.EF.Model.DbVoipCall", b =>
{
b.Property<string>("Id")
.HasColumnType("varchar(50)")
.HasColumnName("id")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<string>("AnsweredBy")
.IsRequired()
.ValueGeneratedOnAdd()
.HasColumnType("varchar(50)")
.HasColumnName("answered_by")
.HasDefaultValueSql("'00000000-0000-0000-0000-000000000000'")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<int>("ContactId")
.HasColumnType("int")
.HasColumnName("contact_id");
b.Property<int?>("CrmContactId")
.HasColumnType("int");
b.Property<DateTime>("DialDate")
.HasColumnType("datetime")
.HasColumnName("dial_date");
b.Property<int>("DialDuration")
.HasColumnType("int")
.HasColumnName("dial_duration");
b.Property<string>("NumberFrom")
.IsRequired()
.HasColumnType("varchar(50)")
.HasColumnName("number_from")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<string>("NumberTo")
.IsRequired()
.HasColumnType("varchar(50)")
.HasColumnName("number_to")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<string>("ParentCallId")
.IsRequired()
.HasColumnType("varchar(50)")
.HasColumnName("parent_call_id")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<decimal>("Price")
.HasColumnType("decimal(10,4)")
.HasColumnName("price");
b.Property<int>("RecordDuration")
.HasColumnType("int")
.HasColumnName("record_duration");
b.Property<decimal>("RecordPrice")
.HasColumnType("decimal(10,4)")
.HasColumnName("record_price");
b.Property<string>("RecordSid")
.HasColumnType("varchar(50)")
.HasColumnName("record_sid")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<string>("RecordUrl")
.HasColumnType("text")
.HasColumnName("record_url")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<int>("Status")
.HasColumnType("int")
.HasColumnName("status");
b.Property<int>("TenantId")
.HasColumnType("int")
.HasColumnName("tenant_id");
b.HasKey("Id");
b.HasIndex("CrmContactId");
b.HasIndex("TenantId")
.HasDatabaseName("tenant_id");
b.HasIndex("ParentCallId", "TenantId")
.HasDatabaseName("parent_call_id");
b.ToTable("crm_voip_calls");
});
modelBuilder.Entity("ASC.Core.Common.EF.Model.VoipNumber", b =>
{
b.Property<string>("Id")
.HasColumnType("varchar(50)")
.HasColumnName("id")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<string>("Alias")
.HasColumnType("varchar(255)")
.HasColumnName("alias")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<string>("Number")
.IsRequired()
.HasColumnType("varchar(50)")
.HasColumnName("number")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<string>("Settings")
.HasColumnType("text")
.HasColumnName("settings")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<int>("TenantId")
.HasColumnType("int")
.HasColumnName("tenant_id");
b.HasKey("Id");
b.HasIndex("TenantId")
.HasDatabaseName("tenant_id");
b.ToTable("crm_voip_number");
});
modelBuilder.Entity("ASC.Core.Common.EF.Model.DbVoipCall", b =>
{
b.HasOne("ASC.Core.Common.EF.Model.CrmContact", "CrmContact")
.WithMany()
.HasForeignKey("CrmContactId");
b.Navigation("CrmContact");
});
#pragma warning restore 612, 618
}
}
}

View File

@ -1,282 +0,0 @@
// <auto-generated />
namespace ASC.Core.Common.Migrations.PostgreSql.VoipDbContextPostgreSql
{
[DbContext(typeof(PostgreSqlVoipDbContext))]
[Migration("20211012145345_VoipDbContextPostgreSql")]
partial class VoipDbContextPostgreSql
{
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("Relational:MaxIdentifierLength", 64)
.HasAnnotation("ProductVersion", "5.0.10");
modelBuilder.Entity("ASC.Core.Common.EF.Model.CrmContact", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int")
.HasColumnName("id");
b.Property<int>("CompanyId")
.HasColumnType("int")
.HasColumnName("company_id");
b.Property<string>("CompanyName")
.HasColumnType("varchar(255)")
.HasColumnName("company_name")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<int>("ContactTypeId")
.HasColumnType("int")
.HasColumnName("contact_type_id");
b.Property<string>("CreateBy")
.IsRequired()
.HasColumnType("char(38)")
.HasColumnName("create_by")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<DateTime>("CreateOn")
.HasColumnType("datetime")
.HasColumnName("create_on");
b.Property<string>("Currency")
.HasColumnType("varchar(3)")
.HasColumnName("currency")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<string>("DisplayName")
.HasColumnType("varchar(255)")
.HasColumnName("display_name")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<string>("FirstName")
.HasColumnType("varchar(255)")
.HasColumnName("first_name")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<string>("Industry")
.HasColumnType("varchar(255)")
.HasColumnName("industry")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<bool>("IsCompany")
.HasColumnType("tinyint(1)")
.HasColumnName("is_company");
b.Property<bool>("IsShared")
.HasColumnType("tinyint(1)")
.HasColumnName("is_shared");
b.Property<string>("LastModifedBy")
.IsRequired()
.HasColumnType("char(38)")
.HasColumnName("last_modifed_by")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<DateTime>("LastModifedOn")
.HasColumnType("datetime")
.HasColumnName("last_modifed_on");
b.Property<string>("LastName")
.HasColumnType("varchar(255)")
.HasColumnName("last_name")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<string>("Notes")
.HasColumnType("text")
.HasColumnName("notes")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<int>("StatusId")
.HasColumnType("int")
.HasColumnName("status_id");
b.Property<int>("TenantId")
.HasColumnType("int")
.HasColumnName("tenant_id");
b.Property<string>("Title")
.HasColumnType("varchar(255)")
.HasColumnName("title")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.HasKey("Id");
b.HasIndex("CreateOn")
.HasDatabaseName("create_on");
b.HasIndex("LastModifedOn", "TenantId")
.HasDatabaseName("last_modifed_on");
b.HasIndex("TenantId", "CompanyId")
.HasDatabaseName("company_id");
b.HasIndex("TenantId", "DisplayName")
.HasDatabaseName("display_name");
b.ToTable("crm_contact");
});
modelBuilder.Entity("ASC.Core.Common.EF.Model.DbVoipCall", b =>
{
b.Property<string>("Id")
.HasColumnType("varchar(50)")
.HasColumnName("id")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<string>("AnsweredBy")
.IsRequired()
.ValueGeneratedOnAdd()
.HasColumnType("varchar(50)")
.HasColumnName("answered_by")
.HasDefaultValueSql("'00000000-0000-0000-0000-000000000000'")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<int>("ContactId")
.HasColumnType("int")
.HasColumnName("contact_id");
b.Property<int?>("CrmContactId")
.HasColumnType("int");
b.Property<DateTime>("DialDate")
.HasColumnType("datetime")
.HasColumnName("dial_date");
b.Property<int>("DialDuration")
.HasColumnType("int")
.HasColumnName("dial_duration");
b.Property<string>("NumberFrom")
.IsRequired()
.HasColumnType("varchar(50)")
.HasColumnName("number_from")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<string>("NumberTo")
.IsRequired()
.HasColumnType("varchar(50)")
.HasColumnName("number_to")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<string>("ParentCallId")
.IsRequired()
.HasColumnType("varchar(50)")
.HasColumnName("parent_call_id")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<decimal>("Price")
.HasColumnType("decimal(10,4)")
.HasColumnName("price");
b.Property<int>("RecordDuration")
.HasColumnType("int")
.HasColumnName("record_duration");
b.Property<decimal>("RecordPrice")
.HasColumnType("decimal(10,4)")
.HasColumnName("record_price");
b.Property<string>("RecordSid")
.HasColumnType("varchar(50)")
.HasColumnName("record_sid")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<string>("RecordUrl")
.HasColumnType("text")
.HasColumnName("record_url")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<int>("Status")
.HasColumnType("int")
.HasColumnName("status");
b.Property<int>("TenantId")
.HasColumnType("int")
.HasColumnName("tenant_id");
b.HasKey("Id");
b.HasIndex("CrmContactId");
b.HasIndex("TenantId")
.HasDatabaseName("tenant_id");
b.HasIndex("ParentCallId", "TenantId")
.HasDatabaseName("parent_call_id");
b.ToTable("crm_voip_calls");
});
modelBuilder.Entity("ASC.Core.Common.EF.Model.VoipNumber", b =>
{
b.Property<string>("Id")
.HasColumnType("varchar(50)")
.HasColumnName("id")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<string>("Alias")
.HasColumnType("varchar(255)")
.HasColumnName("alias")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<string>("Number")
.IsRequired()
.HasColumnType("varchar(50)")
.HasColumnName("number")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<string>("Settings")
.HasColumnType("text")
.HasColumnName("settings")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<int>("TenantId")
.HasColumnType("int")
.HasColumnName("tenant_id");
b.HasKey("Id");
b.HasIndex("TenantId")
.HasDatabaseName("tenant_id");
b.ToTable("crm_voip_number");
});
modelBuilder.Entity("ASC.Core.Common.EF.Model.DbVoipCall", b =>
{
b.HasOne("ASC.Core.Common.EF.Model.CrmContact", "CrmContact")
.WithMany()
.HasForeignKey("CrmContactId");
b.Navigation("CrmContact");
});
#pragma warning restore 612, 618
}
}
}

View File

@ -1,189 +0,0 @@
// (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.Migrations.PostgreSql.VoipDbContextPostgreSql;
public partial class VoipDbContextPostgreSql : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AlterDatabase()
.Annotation("MySql:CharSet", "utf8mb4");
migrationBuilder.CreateTable(
name: "crm_contact",
columns: table => new
{
id = table.Column<int>(type: "int", nullable: false)
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
tenant_id = table.Column<int>(type: "int", nullable: false),
is_company = table.Column<bool>(type: "tinyint(1)", nullable: false),
notes = table.Column<string>(type: "text", nullable: true, collation: "utf8_general_ci")
.Annotation("MySql:CharSet", "utf8"),
title = table.Column<string>(type: "varchar(255)", nullable: true, collation: "utf8_general_ci")
.Annotation("MySql:CharSet", "utf8"),
first_name = table.Column<string>(type: "varchar(255)", nullable: true, collation: "utf8_general_ci")
.Annotation("MySql:CharSet", "utf8"),
last_name = table.Column<string>(type: "varchar(255)", nullable: true, collation: "utf8_general_ci")
.Annotation("MySql:CharSet", "utf8"),
company_name = table.Column<string>(type: "varchar(255)", nullable: true, collation: "utf8_general_ci")
.Annotation("MySql:CharSet", "utf8"),
industry = table.Column<string>(type: "varchar(255)", nullable: true, collation: "utf8_general_ci")
.Annotation("MySql:CharSet", "utf8"),
status_id = table.Column<int>(type: "int", nullable: false),
company_id = table.Column<int>(type: "int", nullable: false),
contact_type_id = table.Column<int>(type: "int", nullable: false),
create_by = table.Column<string>(type: "char(38)", nullable: false, collation: "utf8_general_ci")
.Annotation("MySql:CharSet", "utf8"),
create_on = table.Column<DateTime>(type: "datetime", nullable: false),
last_modifed_by = table.Column<string>(type: "char(38)", nullable: false, collation: "utf8_general_ci")
.Annotation("MySql:CharSet", "utf8"),
last_modifed_on = table.Column<DateTime>(type: "datetime", nullable: false),
display_name = table.Column<string>(type: "varchar(255)", nullable: true, collation: "utf8_general_ci")
.Annotation("MySql:CharSet", "utf8"),
is_shared = table.Column<bool>(type: "tinyint(1)", nullable: false),
currency = table.Column<string>(type: "varchar(3)", nullable: true, collation: "utf8_general_ci")
.Annotation("MySql:CharSet", "utf8")
},
constraints: table =>
{
table.PrimaryKey("PK_crm_contact", x => x.id);
})
.Annotation("MySql:CharSet", "utf8mb4");
migrationBuilder.CreateTable(
name: "crm_voip_number",
columns: table => new
{
id = table.Column<string>(type: "varchar(50)", nullable: false, collation: "utf8_general_ci")
.Annotation("MySql:CharSet", "utf8"),
number = table.Column<string>(type: "varchar(50)", nullable: false, collation: "utf8_general_ci")
.Annotation("MySql:CharSet", "utf8"),
alias = table.Column<string>(type: "varchar(255)", nullable: true, collation: "utf8_general_ci")
.Annotation("MySql:CharSet", "utf8"),
settings = table.Column<string>(type: "text", nullable: true, collation: "utf8_general_ci")
.Annotation("MySql:CharSet", "utf8"),
tenant_id = table.Column<int>(type: "int", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_crm_voip_number", x => x.id);
})
.Annotation("MySql:CharSet", "utf8mb4");
migrationBuilder.CreateTable(
name: "crm_voip_calls",
columns: table => new
{
id = table.Column<string>(type: "varchar(50)", nullable: false, collation: "utf8_general_ci")
.Annotation("MySql:CharSet", "utf8"),
parent_call_id = table.Column<string>(type: "varchar(50)", nullable: false, collation: "utf8_general_ci")
.Annotation("MySql:CharSet", "utf8"),
number_from = table.Column<string>(type: "varchar(50)", nullable: false, collation: "utf8_general_ci")
.Annotation("MySql:CharSet", "utf8"),
number_to = table.Column<string>(type: "varchar(50)", nullable: false, collation: "utf8_general_ci")
.Annotation("MySql:CharSet", "utf8"),
status = table.Column<int>(type: "int", nullable: false),
answered_by = table.Column<string>(type: "varchar(50)", nullable: false, defaultValueSql: "'00000000-0000-0000-0000-000000000000'", collation: "utf8_general_ci")
.Annotation("MySql:CharSet", "utf8"),
dial_date = table.Column<DateTime>(type: "datetime", nullable: false),
dial_duration = table.Column<int>(type: "int", nullable: false),
record_sid = table.Column<string>(type: "varchar(50)", nullable: true, collation: "utf8_general_ci")
.Annotation("MySql:CharSet", "utf8"),
record_url = table.Column<string>(type: "text", nullable: true, collation: "utf8_general_ci")
.Annotation("MySql:CharSet", "utf8"),
record_duration = table.Column<int>(type: "int", nullable: false),
record_price = table.Column<decimal>(type: "decimal(10,4)", nullable: false),
contact_id = table.Column<int>(type: "int", nullable: false),
price = table.Column<decimal>(type: "decimal(10,4)", nullable: false),
tenant_id = table.Column<int>(type: "int", nullable: false),
CrmContactId = table.Column<int>(type: "int", nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_crm_voip_calls", x => x.id);
table.ForeignKey(
name: "FK_crm_voip_calls_crm_contact_CrmContactId",
column: x => x.CrmContactId,
principalTable: "crm_contact",
principalColumn: "id",
onDelete: ReferentialAction.Restrict);
})
.Annotation("MySql:CharSet", "utf8mb4");
migrationBuilder.CreateIndex(
name: "company_id",
table: "crm_contact",
columns: new[] { "tenant_id", "company_id" });
migrationBuilder.CreateIndex(
name: "create_on",
table: "crm_contact",
column: "create_on");
migrationBuilder.CreateIndex(
name: "display_name",
table: "crm_contact",
columns: new[] { "tenant_id", "display_name" });
migrationBuilder.CreateIndex(
name: "last_modifed_on",
table: "crm_contact",
columns: new[] { "last_modifed_on", "tenant_id" });
migrationBuilder.CreateIndex(
name: "IX_crm_voip_calls_CrmContactId",
table: "crm_voip_calls",
column: "CrmContactId");
migrationBuilder.CreateIndex(
name: "parent_call_id",
table: "crm_voip_calls",
columns: new[] { "parent_call_id", "tenant_id" });
migrationBuilder.CreateIndex(
name: "tenant_id",
table: "crm_voip_calls",
column: "tenant_id");
migrationBuilder.CreateIndex(
name: "tenant_id",
table: "crm_voip_number",
column: "tenant_id");
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "crm_voip_calls");
migrationBuilder.DropTable(
name: "crm_voip_number");
migrationBuilder.DropTable(
name: "crm_contact");
}
}

View File

@ -1,281 +0,0 @@
// <auto-generated />
namespace ASC.Core.Common.Migrations.PostgreSql.VoipDbContextPostgreSql
{
[DbContext(typeof(PostgreSqlVoipDbContext))]
partial class PostgreSqlVoipDbContextModelSnapshot : ModelSnapshot
{
protected override void BuildModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("Relational:MaxIdentifierLength", 64)
.HasAnnotation("ProductVersion", "5.0.10");
modelBuilder.Entity("ASC.Core.Common.EF.Model.CrmContact", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int")
.HasColumnName("id");
b.Property<int>("CompanyId")
.HasColumnType("int")
.HasColumnName("company_id");
b.Property<string>("CompanyName")
.HasColumnType("varchar(255)")
.HasColumnName("company_name")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<int>("ContactTypeId")
.HasColumnType("int")
.HasColumnName("contact_type_id");
b.Property<string>("CreateBy")
.IsRequired()
.HasColumnType("char(38)")
.HasColumnName("create_by")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<DateTime>("CreateOn")
.HasColumnType("datetime")
.HasColumnName("create_on");
b.Property<string>("Currency")
.HasColumnType("varchar(3)")
.HasColumnName("currency")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<string>("DisplayName")
.HasColumnType("varchar(255)")
.HasColumnName("display_name")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<string>("FirstName")
.HasColumnType("varchar(255)")
.HasColumnName("first_name")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<string>("Industry")
.HasColumnType("varchar(255)")
.HasColumnName("industry")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<bool>("IsCompany")
.HasColumnType("tinyint(1)")
.HasColumnName("is_company");
b.Property<bool>("IsShared")
.HasColumnType("tinyint(1)")
.HasColumnName("is_shared");
b.Property<string>("LastModifedBy")
.IsRequired()
.HasColumnType("char(38)")
.HasColumnName("last_modifed_by")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<DateTime>("LastModifedOn")
.HasColumnType("datetime")
.HasColumnName("last_modifed_on");
b.Property<string>("LastName")
.HasColumnType("varchar(255)")
.HasColumnName("last_name")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<string>("Notes")
.HasColumnType("text")
.HasColumnName("notes")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<int>("StatusId")
.HasColumnType("int")
.HasColumnName("status_id");
b.Property<int>("TenantId")
.HasColumnType("int")
.HasColumnName("tenant_id");
b.Property<string>("Title")
.HasColumnType("varchar(255)")
.HasColumnName("title")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.HasKey("Id");
b.HasIndex("CreateOn")
.HasDatabaseName("create_on");
b.HasIndex("LastModifedOn", "TenantId")
.HasDatabaseName("last_modifed_on");
b.HasIndex("TenantId", "CompanyId")
.HasDatabaseName("company_id");
b.HasIndex("TenantId", "DisplayName")
.HasDatabaseName("display_name");
b.ToTable("crm_contact");
});
modelBuilder.Entity("ASC.Core.Common.EF.Model.DbVoipCall", b =>
{
b.Property<string>("Id")
.HasColumnType("varchar(50)")
.HasColumnName("id")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<string>("AnsweredBy")
.IsRequired()
.ValueGeneratedOnAdd()
.HasColumnType("varchar(50)")
.HasColumnName("answered_by")
.HasDefaultValueSql("'00000000-0000-0000-0000-000000000000'")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<int>("ContactId")
.HasColumnType("int")
.HasColumnName("contact_id");
b.Property<int?>("CrmContactId")
.HasColumnType("int");
b.Property<DateTime>("DialDate")
.HasColumnType("datetime")
.HasColumnName("dial_date");
b.Property<int>("DialDuration")
.HasColumnType("int")
.HasColumnName("dial_duration");
b.Property<string>("NumberFrom")
.IsRequired()
.HasColumnType("varchar(50)")
.HasColumnName("number_from")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<string>("NumberTo")
.IsRequired()
.HasColumnType("varchar(50)")
.HasColumnName("number_to")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<string>("ParentCallId")
.IsRequired()
.HasColumnType("varchar(50)")
.HasColumnName("parent_call_id")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<decimal>("Price")
.HasColumnType("decimal(10,4)")
.HasColumnName("price");
b.Property<int>("RecordDuration")
.HasColumnType("int")
.HasColumnName("record_duration");
b.Property<decimal>("RecordPrice")
.HasColumnType("decimal(10,4)")
.HasColumnName("record_price");
b.Property<string>("RecordSid")
.HasColumnType("varchar(50)")
.HasColumnName("record_sid")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<string>("RecordUrl")
.HasColumnType("text")
.HasColumnName("record_url")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<int>("Status")
.HasColumnType("int")
.HasColumnName("status");
b.Property<int>("TenantId")
.HasColumnType("int")
.HasColumnName("tenant_id");
b.HasKey("Id");
b.HasIndex("CrmContactId");
b.HasIndex("TenantId")
.HasDatabaseName("tenant_id");
b.HasIndex("ParentCallId", "TenantId")
.HasDatabaseName("parent_call_id");
b.ToTable("crm_voip_calls");
});
modelBuilder.Entity("ASC.Core.Common.EF.Model.VoipNumber", b =>
{
b.Property<string>("Id")
.HasColumnType("varchar(50)")
.HasColumnName("id")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<string>("Alias")
.HasColumnType("varchar(255)")
.HasColumnName("alias")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<string>("Number")
.IsRequired()
.HasColumnType("varchar(50)")
.HasColumnName("number")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<string>("Settings")
.HasColumnType("text")
.HasColumnName("settings")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<int>("TenantId")
.HasColumnType("int")
.HasColumnName("tenant_id");
b.HasKey("Id");
b.HasIndex("TenantId")
.HasDatabaseName("tenant_id");
b.ToTable("crm_voip_number");
});
modelBuilder.Entity("ASC.Core.Common.EF.Model.DbVoipCall", b =>
{
b.HasOne("ASC.Core.Common.EF.Model.CrmContact", "CrmContact")
.WithMany()
.HasForeignKey("CrmContactId");
b.Navigation("CrmContact");
});
#pragma warning restore 612, 618
}
}
}

View File

@ -1,40 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<ApplicationIcon />
<OutputType>Library</OutputType>
<StartupObject />
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
<DebugType>none</DebugType>
<DebugSymbols>false</DebugSymbols>
</PropertyGroup>
<ItemGroup>
<Compile Remove="Properties\**" />
<Compile Remove="VoxImplant\**" />
<EmbeddedResource Remove="Properties\**" />
<EmbeddedResource Remove="VoxImplant\**" />
<None Remove="Properties\**" />
<None Remove="VoxImplant\**" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Grpc.Tools" Version="2.45.0">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Twilio" Version="5.6.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\ASC.Core.Common\ASC.Core.Common.csproj" />
</ItemGroup>
<ItemGroup>
<Protobuf Include="protos\cached_voip_item.proto" />
</ItemGroup>
</Project>

View File

@ -1,64 +0,0 @@
// (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.VoipService.Dao;
public class AbstractDao
{
private readonly string _dbid = "default";
private readonly Lazy<VoipDbContext> _lazyVoipDbContext;
protected VoipDbContext VoipDbContext { get => _lazyVoipDbContext.Value; }
protected int TenantID
{
get;
private set;
}
protected AbstractDao(DbContextManager<VoipDbContext> dbOptions, TenantManager tenantManager)
{
_lazyVoipDbContext = new Lazy<VoipDbContext>(() => dbOptions.Get(_dbid));
TenantID = tenantManager.GetCurrentTenant().Id;
}
protected string GetTenantColumnName(string table)
{
const string tenant = "tenant_id";
if (!table.Contains(' '))
{
return tenant;
}
return table.Substring(table.IndexOf(" ", StringComparison.Ordinal)).Trim() + "." + tenant;
}
protected static Guid ToGuid(object guid)
{
var str = guid as string;
return !string.IsNullOrEmpty(str) ? new Guid(str) : Guid.Empty;
}
}

View File

@ -1,113 +0,0 @@
// (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.VoipService.Dao;
public class VoipCallFilter
{
public string Type { get; set; }
public DateTime? FromDate { get; set; }
public DateTime? ToDate { get; set; }
public Guid? Agent { get; set; }
public int? Client { get; set; }
public int? ContactID { get; set; }
public string Id { get; set; }
public string ParentId { get; set; }
public string SortBy { get; set; }
public bool SortOrder { get; set; }
public string SearchText { get; set; }
public long Offset { get; set; }
public long Max { get; set; }
public int? TypeStatus
{
get
{
if (string.IsNullOrWhiteSpace(Type))
{
return null;
}
if (TypeStatuses.TryGetValue(Type, out var status))
{
return status;
}
return null;
}
}
public string SortByColumn
{
get
{
if (string.IsNullOrWhiteSpace(SortBy))
{
return null;
}
return SortColumns.ContainsKey(SortBy) ? SortColumns[SortBy] : null;
}
}
private static Dictionary<string, int> TypeStatuses
{
get
{
return new Dictionary<string, int>
{
{
"answered", (int)VoipCallStatus.Answered
},
{
"missed", (int)VoipCallStatus.Missed
},
{
"outgoing", (int)VoipCallStatus.Outcoming
}
};
}
}
private static Dictionary<string, string> SortColumns
{
get
{
return new Dictionary<string, string>
{
{
"date", "dial_date"
},
{
"duration", "dial_duration"
},
{
"price", "price"
},
};
}
}
}

View File

@ -1,326 +0,0 @@
// (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.VoipService.Dao;
[Scope(Additional = typeof(EventTypeConverterExtension))]
public class VoipDao : AbstractDao
{
private readonly AuthContext _authContext;
private readonly TenantUtil _tenantUtil;
private readonly SecurityContext _securityContext;
private readonly BaseCommonLinkUtility _baseCommonLinkUtility;
private readonly ConsumerFactory _consumerFactory;
private readonly IMapper _mapper;
public VoipDao(
TenantManager tenantManager,
DbContextManager<VoipDbContext> dbOptions,
AuthContext authContext,
TenantUtil tenantUtil,
SecurityContext securityContext,
BaseCommonLinkUtility baseCommonLinkUtility,
ConsumerFactory consumerFactory,
IMapper mapper)
: base(dbOptions, tenantManager)
{
_authContext = authContext;
_tenantUtil = tenantUtil;
_securityContext = securityContext;
_baseCommonLinkUtility = baseCommonLinkUtility;
_consumerFactory = consumerFactory;
_mapper = mapper;
}
public virtual VoipPhone SaveOrUpdateNumber(VoipPhone phone)
{
if (!string.IsNullOrEmpty(phone.Number))
{
phone.Number = phone.Number.TrimStart('+');
}
var voipNumber = new VoipNumber
{
Id = phone.Id,
Number = phone.Number,
Alias = phone.Alias,
Settings = phone.Settings.ToString(),
TenantId = TenantID
};
VoipDbContext.VoipNumbers.Add(voipNumber);
VoipDbContext.SaveChanges();
return phone;
}
public virtual void DeleteNumber(string phoneId = "")
{
var number = VoipDbContext.VoipNumbers.Where(r => r.Id == phoneId && r.TenantId == TenantID).FirstOrDefault();
VoipDbContext.VoipNumbers.Remove(number);
VoipDbContext.SaveChanges();
}
public virtual IEnumerable<VoipPhone> GetAllNumbers()
{
return VoipDbContext.VoipNumbers
.Where(r => r.TenantId == TenantID)
.ToList()
.ConvertAll(ToPhone);
}
public virtual IEnumerable<VoipPhone> GetNumbers(params string[] ids)
{
var numbers = VoipDbContext.VoipNumbers.Where(r => r.TenantId == TenantID);
if (ids.Length > 0)
{
numbers = numbers.Where(r => ids.Any(a => a == r.Number || a == r.Id));
}
return numbers.ToList().ConvertAll(ToPhone);
}
public VoipPhone GetNumber(string id)
{
return GetNumbers(id.TrimStart('+')).FirstOrDefault();
}
public virtual VoipPhone GetCurrentNumber()
{
return GetNumbers().FirstOrDefault(r => r.Caller != null);
}
public VoipCall SaveOrUpdateCall(VoipCall call)
{
var voipCall = new DbVoipCall
{
TenantId = TenantID,
Id = call.Id,
NumberFrom = call.NumberFrom,
NumberTo = call.NumberTo,
ContactId = call.ContactId
};
if (!string.IsNullOrEmpty(call.ParentCallId))
{
voipCall.ParentCallId = call.ParentCallId;
}
if (call.Status.HasValue)
{
voipCall.Status = (int)call.Status.Value;
}
if (!call.AnsweredBy.Equals(Guid.Empty))
{
voipCall.AnsweredBy = call.AnsweredBy;
}
if (call.DialDate == DateTime.MinValue)
{
call.DialDate = DateTime.UtcNow;
}
voipCall.DialDate = _tenantUtil.DateTimeToUtc(call.DialDate);
if (call.DialDuration > 0)
{
voipCall.DialDuration = call.DialDuration;
}
if (call.Price > decimal.Zero)
{
voipCall.Price = call.Price;
}
if (call.VoipRecord != null)
{
if (!string.IsNullOrEmpty(call.VoipRecord.Sid))
{
voipCall.Sid = call.VoipRecord.Sid;
}
if (!string.IsNullOrEmpty(call.VoipRecord.Uri))
{
voipCall.Uri = call.VoipRecord.Uri;
}
if (call.VoipRecord.Duration != 0)
{
voipCall.Duration = call.VoipRecord.Duration;
}
if (call.VoipRecord.Price != default)
{
voipCall.RecordPrice = call.VoipRecord.Price;
}
}
VoipDbContext.VoipCalls.Add(voipCall);
VoipDbContext.SaveChanges();
return call;
}
public IEnumerable<VoipCall> GetCalls(VoipCallFilter filter)
{
var query = GetCallsQuery(filter);
if (filter.SortByColumn != null)
{
query.OrderBy(filter.SortByColumn, filter.SortOrder);
}
query = query.Skip((int)filter.Offset);
query = query.Take((int)filter.Max * 3);
var calls = _mapper.Map<List<CallContact>, IEnumerable<VoipCall>>(query.ToList());
calls = calls.GroupJoin(calls, call => call.Id, h => h.ParentCallId, (call, h) =>
{
call.ChildCalls.AddRange(h);
return call;
}).Where(r => string.IsNullOrEmpty(r.ParentCallId)).ToList();
return calls;
}
public VoipCall GetCall(string id)
{
return GetCalls(new VoipCallFilter { Id = id }).FirstOrDefault();
}
public int GetCallsCount(VoipCallFilter filter)
{
return GetCallsQuery(filter).Where(r => r.DbVoipCall.ParentCallId == "").Count();
}
public IEnumerable<VoipCall> GetMissedCalls(Guid agent, long count = 0, DateTime? from = null)
{
var query = GetCallsQuery(new VoipCallFilter { Agent = agent, SortBy = "date", SortOrder = true, Type = "missed" });
if (from.HasValue)
{
query = query.Where(r => r.DbVoipCall.DialDate >= _tenantUtil.DateTimeFromUtc(from.Value));
}
if (count != 0)
{
query = query.Take((int)count);
}
query = query.Select(ca => new
{
dbVoipCall = ca,
tmpDate = VoipDbContext.VoipCalls
.Where(tmp => tmp.TenantId == ca.DbVoipCall.TenantId)
.Where(tmp => tmp.NumberFrom == ca.DbVoipCall.NumberFrom || tmp.NumberTo == ca.DbVoipCall.NumberFrom)
.Where(tmp => tmp.Status <= (int)VoipCallStatus.Missed)
.Max(tmp => tmp.DialDate)
}).Where(r => r.dbVoipCall.DbVoipCall.DialDate >= r.tmpDate || r.tmpDate == default)
.Select(q => q.dbVoipCall);
return _mapper.Map<List<CallContact>, IEnumerable<VoipCall>>(query.ToList());
}
private IQueryable<CallContact> GetCallsQuery(VoipCallFilter filter)
{
var q = VoipDbContext.VoipCalls
.Where(r => r.TenantId == TenantID);
if (!string.IsNullOrEmpty(filter.Id))
{
q = q.Where(r => r.Id == filter.Id || r.ParentCallId == filter.Id);
}
if (filter.ContactID.HasValue)
{
q = q.Where(r => r.ContactId == filter.ContactID.Value);
}
if (!string.IsNullOrWhiteSpace(filter.SearchText))
{
q = q.Where(r => r.Id.StartsWith(filter.SearchText));
}
if (filter.TypeStatus.HasValue)
{
q = q.Where(r => r.Status == filter.TypeStatus.Value);
}
if (filter.FromDate.HasValue)
{
q = q.Where(r => r.DialDate >= filter.FromDate.Value);
}
if (filter.ToDate.HasValue)
{
q = q.Where(r => r.DialDate <= filter.ToDate.Value);
}
if (filter.Agent.HasValue)
{
q = q.Where(r => r.AnsweredBy == filter.Agent.Value);
}
return from voipCalls in q
join crmContact in VoipDbContext.CrmContact on voipCalls.ContactId equals crmContact.Id into grouping
from g in grouping.DefaultIfEmpty()
select new CallContact { DbVoipCall = voipCalls, CrmContact = g };
}
private VoipPhone ToPhone(VoipNumber r)
{
return GetProvider().GetPhone(r);
}
public Consumer Consumer
{
get { return _consumerFactory.GetByKey("twilio"); }
}
public TwilioProvider GetProvider()
{
return new TwilioProvider(Consumer["twilioAccountSid"], Consumer["twilioAuthToken"], _authContext, _tenantUtil, _securityContext, _baseCommonLinkUtility);
}
public bool ConfigSettingsExist
{
get
{
return !string.IsNullOrEmpty(Consumer["twilioAccountSid"]) &&
!string.IsNullOrEmpty(Consumer["twilioAuthToken"]);
}
}
}
public class CallContact
{
public DbVoipCall DbVoipCall { get; set; }
public CrmContact CrmContact { get; set; }
}

View File

@ -1,58 +0,0 @@
// (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
global using System.Reflection;
global using System.Text;
global using System.Web;
global using ASC.Common;
global using ASC.Common.Mapping;
global using ASC.Core;
global using ASC.Core.Common;
global using ASC.Core.Common.Configuration;
global using ASC.Core.Common.EF;
global using ASC.Core.Common.EF.Context;
global using ASC.Core.Common.EF.Model;
global using ASC.Core.Tenants;
global using ASC.VoipService.Dao;
global using ASC.VoipService.Mappings;
global using ASC.VoipService.Twilio;
global using AutoMapper;
global using Newtonsoft.Json;
global using Newtonsoft.Json.Linq;
global using Newtonsoft.Json.Serialization;
global using Twilio.Clients;
global using Twilio.Exceptions;
global using Twilio.Jwt;
global using Twilio.Jwt.Client;
global using Twilio.Rest.Api.V2010.Account;
global using Twilio.Rest.Api.V2010.Account.AvailablePhoneNumberCountry;
global using Twilio.Rest.Api.V2010.Account.Queue;
global using Twilio.TwiML;
global using Twilio.Types;

View File

@ -1,54 +0,0 @@
// (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.VoipService;
public interface IVoipProvider
{
IEnumerable<VoipPhone> GetExistingPhoneNumbers();
IEnumerable<VoipPhone> GetAvailablePhoneNumbers(PhoneNumberType phoneNumberType, string isoCountryCode);
VoipPhone BuyNumber(string phoneNumber);
VoipPhone DeleteNumber(VoipPhone phone);
VoipPhone GetPhone(VoipNumber r);
VoipPhone GetPhone(string id);
VoipCall GetCall(string callId);
string GetToken(Agent agent, int seconds = 60 * 60 * 24);
void UpdateSettings(VoipPhone phone);
VoipRecord GetRecord(string callId, string recordId);
void CreateQueue(VoipPhone newPhone);
void DisablePhone(VoipPhone phone);
}

View File

@ -1,60 +0,0 @@
// (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.VoipService.Mappings;
[Scope]
public class CallTypeConverter : ITypeConverter<CallContact, VoipCall>
{
public VoipCall Convert(CallContact source, VoipCall destination, ResolutionContext context)
{
var result = context.Mapper.Map<DbVoipCall, VoipCall>(source.DbVoipCall);
result.VoipRecord = context.Mapper.Map<DbVoipCall, VoipRecord>(source.DbVoipCall);
if (source.CrmContact != null)
{
result.ContactId = source.CrmContact.Id;
result.ContactIsCompany = source.CrmContact.IsCompany;
result.ContactTitle = result.ContactIsCompany
? source.CrmContact.CompanyName
: source.CrmContact.FirstName == null || source.CrmContact.LastName == null ? null : $"{source.CrmContact.FirstName} {source.CrmContact.LastName}";
}
else
{
result.ContactId = 0;
}
return result;
}
}
public class EventTypeConverterExtension
{
public static void Register(DIHelper services)
{
services.TryAdd<CallTypeConverter>();
}
}

View File

@ -1,126 +0,0 @@
// (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
using HttpMethod = Twilio.Http.HttpMethod;
namespace ASC.VoipService.Twilio;
public class TwilioPhone : VoipPhone
{
private readonly TwilioRestClient _twilio;
public TwilioPhone(
TwilioRestClient twilio,
AuthContext authContext,
TenantUtil tenantUtil,
SecurityContext securityContext,
BaseCommonLinkUtility baseCommonLinkUtility) :
base(authContext, tenantUtil, securityContext, baseCommonLinkUtility)
{
_twilio = twilio;
Settings = new TwilioVoipSettings(authContext, tenantUtil, securityContext, baseCommonLinkUtility);
}
#region Calls
public override VoipCall Call(string to, string contactId = null)
{
var number = to.Split('#');
var call = CallResource.Create(new CreateCallOptions(new PhoneNumber("+" + number[0].TrimStart('+')), new PhoneNumber("+" + Number.TrimStart('+')))
{
SendDigits = number.Length > 1 ? number[1] + "#" : string.Empty,
Record = Settings.Caller.Record,
Url = new Uri(Settings.Connect(contactId: contactId))
}, _twilio);
return new VoipCall { Id = call.Sid, NumberFrom = call.From, NumberTo = call.To };
}
public override VoipCall LocalCall(string to)
{
return Call(Number + "#" + to);
}
public override VoipCall RedirectCall(string callId, string to)
{
var call = CallResource.Update(callId, url: new Uri(Settings.Redirect(to)), method: HttpMethod.Post, client: _twilio);
return new VoipCall { Id = call.Sid, NumberTo = to };
}
public override VoipCall HoldUp(string callId)
{
return RedirectCall(callId, "hold");
}
#endregion
#region Queue
public Queue CreateQueue(string name, int size, string waitUrl, int waitTime)
{
var queues = QueueResource.Read(new ReadQueueOptions(), _twilio);
var queue = queues.FirstOrDefault(r => r.FriendlyName == name);
if (queue == null)
{
queue = QueueResource.Create(name, client: _twilio);
}
return new Queue(queue.Sid, name, size, waitUrl, waitTime);
}
public string GetQueue(string name)
{
var queues = QueueResource.Read(new ReadQueueOptions(), _twilio);
return queues.First(r => r.FriendlyName == name).Sid;
}
public IEnumerable<string> QueueCalls(string id)
{
var calls = MemberResource.Read(id, client: _twilio);
return calls.Select(r => r.CallSid);
}
private void AnswerQueueCall(string queueId, string callId, bool reject = false)
{
var calls = QueueCalls(queueId);
if (calls.Contains(callId))
{
MemberResource.Update(queueId, callId, new Uri(Settings.Dequeue(reject)), HttpMethod.Post,
client: _twilio);
}
}
public override void AnswerQueueCall(string callId)
{
AnswerQueueCall(Settings.Queue.Id, callId);
}
public override void RejectQueueCall(string callId)
{
AnswerQueueCall(Settings.Queue.Id, callId, true);
}
#endregion
}

View File

@ -1,232 +0,0 @@
// (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
using RecordingResource = Twilio.Rest.Api.V2010.Account.Call.RecordingResource;
namespace ASC.VoipService.Twilio;
public class TwilioProvider : IVoipProvider
{
private readonly string _accountSid;
private readonly string _authToken;
private readonly TwilioRestClient _client;
private readonly AuthContext _authContext;
private readonly TenantUtil _tenantUtil;
private readonly SecurityContext _securityContext;
private readonly BaseCommonLinkUtility _baseCommonLinkUtility;
public TwilioProvider(string accountSid, string authToken, AuthContext authContext, TenantUtil tenantUtil, SecurityContext securityContext, BaseCommonLinkUtility baseCommonLinkUtility)
{
ArgumentNullOrEmptyException.ThrowIfNullOrEmpty(accountSid);
ArgumentNullOrEmptyException.ThrowIfNullOrEmpty(authToken);
_authToken = authToken;
_authContext = authContext;
_tenantUtil = tenantUtil;
_securityContext = securityContext;
_baseCommonLinkUtility = baseCommonLinkUtility;
_accountSid = accountSid;
_client = new TwilioRestClient(accountSid, authToken);
}
#region Call
public VoipRecord GetRecord(string callId, string recordSid)
{
var result = new VoipRecord { Sid = recordSid };
var count = 6;
while (count > 0)
{
try
{
var record = RecordingResource.Fetch(callId, recordSid, client: _client);
if (!record.Price.HasValue)
{
count--;
Thread.Sleep(10000);
continue;
}
result.Price = (-1) * record.Price.Value;
result.Duration = Convert.ToInt32(record.Duration);
if (record.Uri != null)
{
result.Uri = record.Uri;
}
break;
}
catch (ApiException)
{
count--;
Thread.Sleep(10000);
}
}
return result;
}
public void CreateQueue(VoipPhone newPhone)
{
newPhone.Settings.Queue = ((TwilioPhone)newPhone).CreateQueue(newPhone.Number, 5, string.Empty, 5);
}
#endregion
#region Numbers
public VoipPhone BuyNumber(string phoneNumber)
{
var newNumber = IncomingPhoneNumberResource.Create(
new CreateIncomingPhoneNumberOptions
{
PathAccountSid = _accountSid,
PhoneNumber = new PhoneNumber(phoneNumber)
}, _client);
return new TwilioPhone(_client, _authContext, _tenantUtil, _securityContext, _baseCommonLinkUtility) { Id = newNumber.Sid, Number = phoneNumber.Substring(1) };
}
public VoipPhone DeleteNumber(VoipPhone phone)
{
IncomingPhoneNumberResource.Delete(phone.Id, client: _client);
return phone;
}
public IEnumerable<VoipPhone> GetExistingPhoneNumbers()
{
var result = IncomingPhoneNumberResource.Read(client: _client);
return result.Select(r => new TwilioPhone(_client, _authContext, _tenantUtil, _securityContext, _baseCommonLinkUtility) { Id = r.Sid, Number = r.PhoneNumber.ToString() });
}
public IEnumerable<VoipPhone> GetAvailablePhoneNumbers(PhoneNumberType phoneNumberType, string isoCountryCode)
{
return phoneNumberType switch
{
PhoneNumberType.Local => LocalResource.Read(isoCountryCode, voiceEnabled: true, client: _client).Select(r => new TwilioPhone(_client, _authContext, _tenantUtil, _securityContext, _baseCommonLinkUtility) { Number = r.PhoneNumber.ToString() }),
PhoneNumberType.TollFree => TollFreeResource.Read(isoCountryCode, voiceEnabled: true, client: _client).Select(r => new TwilioPhone(_client, _authContext, _tenantUtil, _securityContext, _baseCommonLinkUtility) { Number = r.PhoneNumber.ToString() }),
_ => new List<VoipPhone>(),
};
}
public VoipPhone GetPhone(string phoneSid)
{
var phone = IncomingPhoneNumberResource.Fetch(phoneSid, client: _client);
var result = new TwilioPhone(_client, _authContext, _tenantUtil, _securityContext, _baseCommonLinkUtility)
{
Id = phone.Sid,
Number = phone.PhoneNumber.ToString(),
Settings = new TwilioVoipSettings(_authContext, _tenantUtil, _securityContext, _baseCommonLinkUtility)
};
if (phone.VoiceUrl == null)
{
result.Settings.VoiceUrl = result.Settings.Connect(false);
}
return result;
}
public VoipPhone GetPhone(VoipNumber data)
{
return new TwilioPhone(_client, _authContext, _tenantUtil, _securityContext, _baseCommonLinkUtility)
{
Id = data.Id,
Number = data.Number,
Alias = data.Alias,
Settings = new TwilioVoipSettings(data.Settings, _authContext)
};
}
public VoipCall GetCall(string callId)
{
var result = new VoipCall { Id = callId };
var count = 6;
while (count > 0)
{
try
{
var call = CallResource.Fetch(result.Id, client: _client);
if (!call.Price.HasValue || string.IsNullOrEmpty(call.Duration))
{
count--;
Thread.Sleep(10000);
continue;
}
result.Price = (-1) * call.Price.Value;
result.DialDuration = Convert.ToInt32(call.Duration);
break;
}
catch (ApiException)
{
count--;
Thread.Sleep(10000);
}
}
return result;
}
public string GetToken(Agent agent, int seconds = 60 * 60 * 24)
{
var scopes = new HashSet<IScope>
{
new IncomingClientScope(agent.ClientID)
};
var capability = new ClientCapability(_accountSid, _authToken, scopes: scopes);
return capability.ToJwt();
}
public void UpdateSettings(VoipPhone phone)
{
IncomingPhoneNumberResource.Update(phone.Id, voiceUrl: new Uri(phone.Settings.Connect(false)), client: _client);
}
public void DisablePhone(VoipPhone phone)
{
IncomingPhoneNumberResource.Update(phone.Id, voiceUrl: new Uri("https://demo.twilio.com/welcome/voice/"), client: _client);
}
#endregion
}
public enum PhoneNumberType
{
Local,
/* Mobile,*/
TollFree
}

View File

@ -1,216 +0,0 @@
// (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.VoipService.Twilio;
public class TwilioResponseHelper
{
private readonly VoipSettings _settings;
private readonly string _baseUrl;
private readonly AuthContext _authContext;
private readonly TenantUtil _tenantUtil;
private readonly SecurityContext _securityContext;
public TwilioResponseHelper(
VoipSettings settings,
string baseUrl,
AuthContext authContext,
TenantUtil tenantUtil,
SecurityContext securityContext)
{
_settings = settings;
_authContext = authContext;
_tenantUtil = tenantUtil;
_securityContext = securityContext;
_baseUrl = baseUrl.TrimEnd('/') + "/twilio/";
}
public VoiceResponse Inbound(Tuple<Agent, bool> agentTuple)
{
var agent = agentTuple?.Item1;
var anyOnline = agentTuple != null && agentTuple.Item2;
var response = new VoiceResponse();
if (_settings.WorkingHours != null && _settings.WorkingHours.Enabled)
{
var now = _tenantUtil.DateTimeFromUtc(DateTime.UtcNow);
if (!(_settings.WorkingHours.From <= now.TimeOfDay && _settings.WorkingHours.To >= now.TimeOfDay))
{
return AddVoiceMail(response);
}
}
if (anyOnline)
{
if (!string.IsNullOrEmpty(_settings.GreetingAudio))
{
response.Play(Uri.EscapeDataString(_settings.GreetingAudio));
}
response.Enqueue(_settings.Queue.Name, GetEcho("Enqueue", agent != null), "POST",
GetEcho("Wait", agent != null), "POST");
}
return AddVoiceMail(response);
}
public VoiceResponse Outbound()
{
return !_settings.Caller.AllowOutgoingCalls
? new VoiceResponse()
: AddToResponse(new VoiceResponse(), _settings.Caller);
}
public VoiceResponse Dial()
{
return new VoiceResponse();
}
public VoiceResponse Queue()
{
return new VoiceResponse();
}
public VoiceResponse Enqueue(string queueResult)
{
return queueResult == "leave" ? AddVoiceMail(new VoiceResponse()) : new VoiceResponse();
}
public VoiceResponse Dequeue()
{
return AddToResponse(new VoiceResponse(), _settings.Caller);
}
public VoiceResponse Leave()
{
return AddVoiceMail(new VoiceResponse());
}
public VoiceResponse Wait(string queueTime, string queueSize)
{
var response = new VoiceResponse();
var queue = _settings.Queue;
if (Convert.ToInt32(queueTime) > queue.WaitTime || Convert.ToInt32(queueSize) > queue.Size)
{
return response.Leave();
}
if (!string.IsNullOrEmpty(queue.WaitUrl))
{
var gather = new Gather(method: "POST", action: GetEcho("gatherQueue"));
gather.Play(Uri.EscapeDataString(queue.WaitUrl));
response.Gather(gather);
}
else
{
response.Pause(queue.WaitTime);
}
return response;
}
public VoiceResponse GatherQueue(string digits, List<Agent> availableOperators)
{
var response = new VoiceResponse();
if (digits == "#")
{
return AddVoiceMail(response);
}
var oper = _settings.Operators.Find(r => r.PostFix == digits && availableOperators.Contains(r)) ??
_settings.Operators.FirstOrDefault(r => availableOperators.Contains(r));
return oper != null ? AddToResponse(response, oper) : response;
}
public VoiceResponse Redirect(string to)
{
if (to == "hold")
{
return new VoiceResponse().Play(Uri.EscapeDataString(_settings.HoldAudio), 0);
}
if (Guid.TryParse(to, out var newCallerId))
{
_securityContext.AuthenticateMeWithoutCookie(newCallerId);
}
return new VoiceResponse().Enqueue(_settings.Queue.Name, GetEcho("enqueue"), "POST",
GetEcho("wait") + "&RedirectTo=" + to, "POST");
}
public VoiceResponse VoiceMail()
{
return new VoiceResponse();
}
private VoiceResponse AddToResponse(VoiceResponse response, Agent agent)
{
var dial = new Dial(method: "POST", action: GetEcho("dial"), timeout: agent.TimeOut, record: agent.Record ? "record-from-answer" : "do-not-record");
switch (agent.Answer)
{
case AnswerType.Number:
response.Dial(dial.Number(agent.PhoneNumber, method: "POST", url: GetEcho("client")));
break;
case AnswerType.Client:
response.Dial(dial.Client(agent.ClientID, "POST", GetEcho("client")));
break;
case AnswerType.Sip:
response.Dial(dial.Sip(agent.ClientID, method: "POST", url: GetEcho("client")));
break;
}
return response;
}
private VoiceResponse AddVoiceMail(VoiceResponse response)
{
return string.IsNullOrEmpty(_settings.VoiceMail)
? response.Say("")
: response.Play(Uri.EscapeDataString(_settings.VoiceMail)).Record(method: "POST", action: GetEcho("voiceMail"), maxLength: 30);
}
public string GetEcho(string action, bool user = true)
{
var result = _baseUrl.TrimEnd('/');
if (!string.IsNullOrEmpty(action))
{
result += "/" + action.TrimStart('/');
}
if (user)
{
result += "?CallerId=" + _authContext.CurrentAccount.ID;
}
return result;
}
}

View File

@ -1,85 +0,0 @@
// (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
using Uri = System.Uri;
namespace ASC.VoipService.Twilio;
public class TwilioVoipSettings : VoipSettings
{
public TwilioVoipSettings(
AuthContext authContext,
TenantUtil tenantUtil,
SecurityContext securityContext,
BaseCommonLinkUtility baseCommonLinkUtility) :
base(authContext, tenantUtil, securityContext, baseCommonLinkUtility)
{ }
public TwilioVoipSettings(
Uri voiceUrl,
AuthContext authContext,
TenantUtil tenantUtil,
SecurityContext securityContext,
BaseCommonLinkUtility baseCommonLinkUtility) :
this(authContext, tenantUtil, securityContext, baseCommonLinkUtility)
{
if (string.IsNullOrEmpty(voiceUrl.Query))
{
return;
}
JsonSettings = Encoding.UTF8.GetString(Convert.FromBase64String(HttpUtility.UrlDecode(HttpUtility.ParseQueryString(voiceUrl.Query)["settings"])));
}
public TwilioVoipSettings(string settings, AuthContext authContext) : base(settings, authContext)
{
}
public override string Connect(bool user = true, string contactId = null)
{
var result = GetEcho("", user);
if (!string.IsNullOrEmpty(contactId))
{
result += "&ContactId=" + contactId;
}
return result;
}
public override string Redirect(string to)
{
return GetEcho("redirect") + "&RedirectTo=" + to;
}
public override string Dequeue(bool reject)
{
return GetEcho("dequeue") + "&Reject=" + reject;
}
private string GetEcho(string method, bool user = true)
{
return new TwilioResponseHelper(this, BaseCommonLinkUtility.GetFullAbsolutePath(""), AuthContext, TenantUtil, SecurityContext).GetEcho(method, user);
}
}

View File

@ -1,69 +0,0 @@
// (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.VoipService;
public class VoipCall : IMapFrom<CallContact>
{
public string Id { get; set; }
public string ParentCallId { get; set; }
public string NumberFrom { get; set; }
public string NumberTo { get; set; }
public Guid AnsweredBy { get; set; }
public DateTime DialDate { get; set; }
public int DialDuration { get; set; }
public VoipCallStatus? Status { get; set; }
public decimal Price { get; set; }
public int ContactId { get; set; }
public bool ContactIsCompany { get; set; }
public string ContactTitle { get; set; }
public DateTime Date { get; set; }
public DateTime EndDialDate { get; set; }
public VoipRecord VoipRecord { get; set; }
public List<VoipCall> ChildCalls { get; set; }
public VoipCall()
{
ChildCalls = new List<VoipCall>();
VoipRecord = new VoipRecord();
}
public void Mapping(Profile profile)
{
profile.CreateMap<DbVoipCall, VoipCall>();
profile.CreateMap<CallContact, VoipCall>()
.ConvertUsing<CallTypeConverter>();
}
}
public enum VoipCallStatus
{
Incoming,
Outcoming,
Answered,
Missed
}

View File

@ -1,163 +0,0 @@
// (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.VoipService;
public class Agent
{
public Guid Id { get; set; }
public AnswerType Answer { get; set; }
public string ClientID { get { return PhoneNumber + PostFix; } }
public bool Record { get; set; }
public int TimeOut { get; set; }
public AgentStatus Status { get; set; }
public bool AllowOutgoingCalls { get; set; }
public string PostFix { get; set; }
public string PhoneNumber { get; set; }
public string RedirectToNumber { get; set; }
public Agent()
{
Status = AgentStatus.Offline;
TimeOut = 30;
AllowOutgoingCalls = true;
Record = true;
}
public Agent(Guid id, AnswerType answer, VoipPhone phone, string postFix)
: this()
{
Id = id;
Answer = answer;
PhoneNumber = phone.Number;
AllowOutgoingCalls = phone.Settings.AllowOutgoingCalls;
Record = phone.Settings.Record;
PostFix = postFix;
}
}
public class Queue
{
public string Id { get; set; }
public string Name { get; set; }
public int Size { get; set; }
public string WaitUrl { get; set; }
public int WaitTime { get; set; }
public Queue() { }
public Queue(string id, string name, int size, string waitUrl, int waitTime)
{
Id = id;
Name = name;
WaitUrl = waitUrl;
WaitTime = waitTime;
Size = size;
}
}
public sealed class WorkingHours
{
public bool Enabled { get; set; }
public TimeSpan? From { get; set; }
public TimeSpan? To { get; set; }
public WorkingHours() { }
public WorkingHours(TimeSpan from, TimeSpan to)
{
From = from;
To = to;
}
private bool Equals(WorkingHours other)
{
return Enabled.Equals(other.Enabled) && From.Equals(other.From) && To.Equals(other.To);
}
public override bool Equals(object obj)
{
if (obj is null)
{
return false;
}
if (ReferenceEquals(this, obj))
{
return true;
}
if (obj.GetType() != GetType())
{
return false;
}
return Equals((WorkingHours)obj);
}
public override int GetHashCode()
{
return HashCode.Combine(Enabled, From, To);
}
}
public class VoipUpload
{
public string Name { get; set; }
public string Path { get; set; }
public AudioType AudioType { get; set; }
public bool IsDefault { get; set; }
}
public enum AnswerType
{
Number,
Sip,
Client
}
public enum GreetingMessageVoice
{
Man,
Woman,
Alice
}
public enum AgentStatus
{
Online,
Paused,
Offline
}
public enum AudioType
{
Greeting,
HoldUp,
VoiceMail,
Queue
}

View File

@ -1,88 +0,0 @@
// (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.VoipService;
public class VoipPhone
{
public string Id { get; set; }
public string Number { get; set; }
public string Alias { get; set; }
public VoipSettings Settings { get; set; }
public Agent Caller
{
get { return Settings.Caller; }
}
public VoipPhone(AuthContext authContext, TenantUtil tenantUtil, SecurityContext securityContext, BaseCommonLinkUtility baseCommonLinkUtility)
{
Settings = new VoipSettings(authContext, tenantUtil, securityContext, baseCommonLinkUtility);
}
public virtual VoipCall Call(string to, string contactId = null)
{
throw new NotImplementedException();
}
public virtual VoipCall LocalCall(string to)
{
throw new NotImplementedException();
}
public virtual VoipCall RedirectCall(string callId, string to)
{
throw new NotImplementedException();
}
public virtual VoipCall HoldUp(string callId)
{
throw new NotImplementedException();
}
public virtual void AnswerQueueCall(string callId)
{
throw new NotImplementedException();
}
public virtual void RejectQueueCall(string callId)
{
throw new NotImplementedException();
}
}
public class VoipRecord : IMapFrom<DbVoipCall>
{
public string Sid { get; set; }
public string Uri { get; set; }
public int Duration { get; set; }
public decimal Price { get; set; }
public void Mapping(Profile profile)
{
profile.CreateMap<DbVoipCall, VoipRecord>()
.ForMember(dest => dest.Price, opt => opt.MapFrom(src => src.RecordPrice));
}
}

View File

@ -1,175 +0,0 @@
// (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.VoipService;
public class VoipSettings
{
public string VoiceUrl { get; set; }
public string Name { get; set; }
public List<Agent> Operators { get; set; }
public Queue Queue { get; set; }
public Agent Caller { get { return Operators.FirstOrDefault(r => r.Id == AuthContext.CurrentAccount.ID); } }
public WorkingHours WorkingHours { get; set; }
public string VoiceMail { get; set; }
public string GreetingAudio { get; set; }
public string HoldAudio { get; set; }
public bool AllowOutgoingCalls { get; set; }
public bool Pause { get; set; }
public bool Record { get; set; }
internal string JsonSettings
{
get
{
return JsonConvert.SerializeObject(
new
{
Operators,
GreetingAudio,
Name,
Queue,
WorkingHours,
VoiceMail,
HoldAudio,
AllowOutgoingCalls,
Pause,
Record
},
new JsonSerializerSettings { ContractResolver = CustomSerializeContractResolver.Instance });
}
set
{
try
{
var settings = JsonConvert.DeserializeObject<VoipSettings>(value, new JsonSerializerSettings { ContractResolver = CustomSerializeContractResolver.Instance });
Operators = settings.Operators ?? new List<Agent>();
Name = settings.Name;
Queue = settings.Queue;
WorkingHours = settings.WorkingHours;
GreetingAudio = settings.GreetingAudio;
VoiceMail = settings.VoiceMail;
HoldAudio = settings.HoldAudio;
AllowOutgoingCalls = settings.AllowOutgoingCalls;
Pause = settings.Pause;
Record = settings.Record;
}
catch (Exception)
{
}
}
}
protected AuthContext AuthContext { get; }
protected TenantUtil TenantUtil { get; }
protected SecurityContext SecurityContext { get; }
protected BaseCommonLinkUtility BaseCommonLinkUtility { get; }
public VoipSettings(AuthContext authContext, TenantUtil tenantUtil, SecurityContext securityContext, BaseCommonLinkUtility baseCommonLinkUtility)
{
Operators = new List<Agent>();
AuthContext = authContext;
TenantUtil = tenantUtil;
SecurityContext = securityContext;
BaseCommonLinkUtility = baseCommonLinkUtility;
}
public VoipSettings(string settings, AuthContext authContext)
{
JsonSettings = settings;
AuthContext = authContext;
}
public virtual string Connect(bool user = true, string contactId = null)
{
throw new NotImplementedException();
}
public virtual string Redirect(string to)
{
throw new NotImplementedException();
}
public virtual string Dequeue(bool reject)
{
throw new NotImplementedException();
}
public override string ToString()
{
return JsonSettings;
}
public VoipSettings GetSettings(string settings)
{
return new VoipSettings(AuthContext, TenantUtil, SecurityContext, BaseCommonLinkUtility) { JsonSettings = settings };
}
}
class CustomSerializeContractResolver : CamelCasePropertyNamesContractResolver
{
public static readonly CustomSerializeContractResolver Instance = new CustomSerializeContractResolver();
protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
{
var property = base.CreateProperty(member, memberSerialization);
if (property.PropertyName == "voiceMail")
{
property.Converter = new VoiceMailConverter();
}
return property;
}
}
class VoiceMailConverter : JsonConverter
{
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
serializer.Serialize(writer, value);
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
if (reader.ValueType != null && reader.ValueType.Name == "String")
{
return reader.Value;
}
var jObject = JObject.Load(reader);
var url = jObject.Value<string>("url");
return !string.IsNullOrEmpty(url) ? url : "";
}
public override bool CanConvert(Type objectType)
{
return true;
}
}

View File

@ -1,7 +0,0 @@
syntax = "proto3";
package ASC.VoipService.Dao;
message CachedVoipItem {
int32 tenant = 1;
}

View File

@ -106,11 +106,6 @@
<AutoGen>True</AutoGen>
<DependentUpon>CRMTaskResource.resx</DependentUpon>
</Compile>
<Compile Update="Resources\CRMVoipResource.Designer.cs">
<DesignTime>True</DesignTime>
<AutoGen>True</AutoGen>
<DependentUpon>CRMVoipResource.resx</DependentUpon>
</Compile>
<Compile Update="Services\NotifyService\CRMPatternResource.Designer.cs">
<DesignTime>True</DesignTime>
<AutoGen>True</AutoGen>
@ -167,10 +162,6 @@
<Generator>PublicResXFileCodeGenerator</Generator>
<LastGenOutput>CRMTaskResource.Designer.cs</LastGenOutput>
</EmbeddedResource>
<EmbeddedResource Update="Resources\CRMVoipResource.resx">
<Generator>PublicResXFileCodeGenerator</Generator>
<LastGenOutput>CRMVoipResource.Designer.cs</LastGenOutput>
</EmbeddedResource>
<EmbeddedResource Update="Services\NotifyService\CRMPatternResource.resx">
<Generator>PublicResXFileCodeGenerator</Generator>
<LastGenOutput>CRMPatternResource.Designer.cs</LastGenOutput>

File diff suppressed because it is too large Load Diff

View File

@ -1,16 +0,0 @@
using System;
using ASC.VoipService;
namespace ASC.CRM.ApiModels
{
public class CreateVoipCallRequestDto
{
public string From { get; set; }
public string To { get; set; }
public Guid AnsweredBy { get; set; }
public VoipCallStatus? Status { get; set; }
public string ContactId { get; set; }
public decimal? Price { get; set; }
}
}

View File

@ -1,54 +0,0 @@
/*
*
* (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.
*
*/
using System.Collections.Generic;
using ASC.Api.Core;
using ASC.Common.Mapping;
using ASC.VoipService;
using ASC.Web.Api.Models;
namespace ASC.CRM.ApiModels
{
public class VoipCallDto : IMapFrom<VoipCall>
{
public string Id { get; set; }
public string From { get; set; }
public string To { get; set; }
public VoipCallStatus? Status { get; set; }
public EmployeeDto AnsweredBy { get; set; }
public ApiDateTime DialDate { get; set; }
public int DialDuration { get; set; }
public decimal Cost { get; set; }
public ContactDto Contact { get; set; }
public IEnumerable<VoipCallDto> Calls { get; set; }
public string RecordUrl { get; set; }
public int RecordDuration { get; set; }
}
}

View File

@ -1,73 +0,0 @@
/*
*
* (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.
*
*/
using System;
using System.Collections.Generic;
using ASC.Core.Notify.Signalr;
using ASC.VoipService;
namespace ASC.Web.CRM.Classes
{
public class SignalRHelper
{
private readonly string numberId;
private SignalrServiceClient _signalrServiceClient;
public SignalRHelper(string numberId,
SignalrServiceClient signalrServiceClient)
{
_signalrServiceClient = signalrServiceClient;
this.numberId = numberId.TrimStart('+');
}
public void Enqueue(string call, string agent)
{
_signalrServiceClient.EnqueueCall(numberId, call, agent);
}
public void Incoming(string call, string agent)
{
_signalrServiceClient.IncomingCall(call, agent);
}
public void MissCall(string call, string agent)
{
_signalrServiceClient.MissCall(numberId, call, agent);
}
public void Reload(string agentId = null)
{
_signalrServiceClient.Reload(numberId, agentId);
}
public Tuple<Agent, bool> GetAgent(List<Guid> contactsResponsibles)
{
return _signalrServiceClient.GetAgent<Tuple<Agent, bool>>(numberId, contactsResponsibles);
}
}
}

View File

@ -1,538 +0,0 @@
///*
// *
// * (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.
// *
//*/
//using ASC.Common;
//using ASC.Common.Logging;
//using ASC.Core;
//using ASC.Core.Common.Configuration;
//using ASC.Core.Notify.Signalr;
//using ASC.CRM.Core;
//using ASC.CRM.Core.Dao;
//using ASC.CRM.Core.Entities;
//using ASC.VoipService;
//using ASC.VoipService.Twilio;
//using ASC.Web.Studio.Utility;
//using Autofac;
//using Microsoft.AspNetCore.Http;
//using Microsoft.AspNetCore.Mvc;
//using Microsoft.AspNetCore.Mvc.Filters;
//using Microsoft.Extensions.Options;
//using System;
//using System.Collections.Generic;
//using System.Linq;
//using System.Net;
//using System.Net.Http;
//using System.Text;
//using System.Web;
//using Twilio.AspNet.Common;
//using Twilio.AspNet.Core;
//using Twilio.TwiML;
//namespace ASC.Web.CRM.Classes
//{
// [ServiceFilter(typeof(ValidateRequestFilter))]
// public class TwilioController : ApiController
// {
// public TwilioController(IOptionsMonitor<ILog> logger,
// DaoFactory daoFactory,
// VoipEngine voipEngine,
// TenantManager tenantManager,
// SecurityContext securityContext)
// {
// TenantManager = tenantManager;
// Log = logger.Get("ASC");
// DaoFactory = daoFactory;
// VoipEngine = voipEngine;
// SecurityContext = securityContext;
// }
// public SecurityContext SecurityContext { get; }
// public TenantManager TenantManager { get; }
// public VoipEngine VoipEngine { get; }
// public DaoFactory DaoFactory { get; }
// private readonly ILog Log;
// private static readonly object LockObj = new object();
// [System.Web.Http.HttpPost]
// public HttpResponseMessage Index(TwilioVoiceRequest request, [FromUri]Guid? callerId = null, [FromUri]int contactId = 0)
// {
// try
// {
// lock (LockObj)
// {
// request.AddAdditionalFields(callerId, contactId);
// var response = request.IsInbound ? Inbound(request, DaoFactory) : Outbound(request, DaoFactory);
// return GetHttpResponse(response);
// }
// }
// catch (Exception e)
// {
// Log.Error(e);
// throw;
// }
// }
// [System.Web.Http.HttpPost]
// public HttpResponseMessage Client(TwilioVoiceRequest request, [FromUri]Guid callerId)
// {
// try
// {
// request.AddAdditionalFields(callerId);
// VoipEngine.SaveOrUpdateCall(CallFromTwilioRequest(request));
// return GetHttpResponse(new VoiceResponse());
// }
// catch (Exception e)
// {
// Log.Error(e);
// throw;
// }
// }
// [System.Web.Http.HttpPost]
// public HttpResponseMessage Dial(TwilioVoiceRequest request, [FromUri]Guid callerId, [FromUri]int contactId = 0, [FromUri]string reject = null)
// {
// try
// {
// request.AddAdditionalFields(callerId, contactId, reject);
// var call = CallFromTwilioRequest(request);
// call = VoipEngine.SaveOrUpdateCall(call);
// var parentCall = DaoFactory.GetVoipDao().GetCall(call.ParentID);
// if (!string.IsNullOrEmpty(request.RecordingSid))
// {
// if (parentCall.VoipRecord == null || string.IsNullOrEmpty(parentCall.VoipRecord.Id))
// {
// parentCall.VoipRecord = new VoipRecord { Id = request.RecordingSid };
// }
// DaoFactory.GetVoipDao().SaveOrUpdateCall(parentCall);
// }
// VoipEngine.SaveAdditionalInfo(parentCall.Id);
// return GetHttpResponse(request.Dial());
// }
// catch (Exception e)
// {
// Log.Error(e);
// throw;
// }
// }
// [System.Web.Http.HttpPost]
// public HttpResponseMessage Enqueue(TwilioVoiceRequest request, [FromUri]Guid? callerId = null, [FromUri]int contactId = 0)
// {
// try
// {
// request.AddAdditionalFields(callerId, contactId);
// if (request.QueueResult != "bridged" && request.QueueResult != "redirected")
// {
// MissCall(request, VoipEngine);
// }
// return GetHttpResponse(request.Enqueue(request.QueueResult));
// }
// catch (Exception e)
// {
// Log.Error(e);
// throw;
// }
// }
// [System.Web.Http.HttpPost]
// public HttpResponseMessage Queue(TwilioVoiceRequest request, [FromUri]Guid? callerId = null, [FromUri]int contactId = 0)
// {
// try
// {
// request.AddAdditionalFields(callerId, contactId);
// return GetHttpResponse(request.Queue());
// }
// catch (Exception e)
// {
// Log.Error(e);
// throw;
// }
// }
// [System.Web.Http.HttpPost]
// public HttpResponseMessage Dequeue(TwilioVoiceRequest request, [FromUri]Guid? callerId = null, [FromUri]int contactId = 0, [FromUri]string reject = "")
// {
// try
// {
// request.AddAdditionalFields(callerId, contactId, reject);
// if (Convert.ToBoolean(request.Reject))
// {
// MissCall(request, VoipEngine);
// return GetHttpResponse(request.Leave());
// }
// VoipEngine.AnswerCall(CallFromTwilioRequest(request));
// return GetHttpResponse(request.Dequeue());
// }
// catch (Exception e)
// {
// Log.Error(e);
// throw;
// }
// }
// [System.Web.Http.HttpPost]
// public HttpResponseMessage Wait(TwilioVoiceRequest request, [FromUri]Guid? callerId = null, [FromUri]int contactId = 0, [FromUri]string redirectTo = null)
// {
// try
// {
// request.AddAdditionalFields(callerId, contactId, redirectTo: redirectTo);
// if (Convert.ToInt32(request.QueueTime) == 0)
// {
// var history = CallFromTwilioRequest(request);
// history.ParentID = history.Id;
// VoipEngine.SaveOrUpdateCall(history);
// var to = request.RedirectTo;
// if (string.IsNullOrEmpty(to))
// {
// request.GetSignalRHelper()
// .Enqueue(request.CallSid, callerId.HasValue ? callerId.Value.ToString() : "");
// }
// else
// {
// request.GetSignalRHelper().Incoming(request.CallSid, to);
// }
// }
// return GetHttpResponse(request.Wait());
// }
// catch (Exception e)
// {
// Log.Error(e);
// throw;
// }
// }
// [System.Web.Http.HttpPost]
// public HttpResponseMessage GatherQueue(TwilioVoiceRequest request, [FromUri]Guid? callerId = null, [FromUri]int contactId = 0)
// {
// try
// {
// request.AddAdditionalFields(callerId, contactId);
// return GetHttpResponse(request.GatherQueue());
// }
// catch (Exception e)
// {
// Log.Error(e);
// throw;
// }
// }
// [System.Web.Http.HttpPost]
// public HttpResponseMessage Redirect(TwilioVoiceRequest request, [FromUri]string redirectTo, [FromUri]Guid? callerId = null)
// {
// try
// {
// request.AddAdditionalFields(callerId, redirectTo: redirectTo);
// return GetHttpResponse(request.Redirect());
// }
// catch (Exception e)
// {
// Log.Error(e);
// throw;
// }
// }
// [System.Web.Http.HttpPost]
// public HttpResponseMessage VoiceMail(TwilioVoiceRequest request, [FromUri]Guid? callerId = null, [FromUri]int contactId = 0)
// {
// try
// {
// request.AddAdditionalFields(callerId, contactId);
// MissCall(request, VoipEngine);
// return GetHttpResponse(request.VoiceMail());
// }
// catch (Exception e)
// {
// Log.Error(e);
// throw;
// }
// }
// private VoiceResponse Inbound(TwilioVoiceRequest request, DaoFactory daoFactory)
// {
// SecurityContext.AuthenticateMe(TenantManager.GetCurrentTenant().OwnerId);
// var call = SaveCall(request, VoipCallStatus.Incoming, daoFactory);
// return request.Inbound(call, daoFactory);
// }
// private VoiceResponse Outbound(TwilioVoiceRequest request, DaoFactory daoFactory)
// {
// SaveCall(request, VoipCallStatus.Outcoming, daoFactory);
// var history = CallFromTwilioRequest(request);
// history.ParentID = history.Id;
// VoipEngine.SaveOrUpdateCall(history);
// return request.Outbound();
// }
// private VoipCall SaveCall(TwilioVoiceRequest request, VoipCallStatus status, DaoFactory daoFactory)
// {
// var call = CallFromTwilioRequest(request);
// call.Status = status;
// return DaoFactory.GetVoipDao().SaveOrUpdateCall(call);
// }
// private void MissCall(TwilioVoiceRequest request, VoipEngine voipEngine)
// {
// var voipCall = CallFromTwilioRequest(request);
// voipCall.Status = VoipCallStatus.Missed;
// if (!string.IsNullOrEmpty(request.RecordingSid))
// {
// if (voipCall.VoipRecord == null || string.IsNullOrEmpty(voipCall.VoipRecord.Id))
// {
// voipCall.VoipRecord = new VoipRecord { Id = request.RecordingSid };
// }
// }
// voipCall = voipEngine.SaveOrUpdateCall(voipCall);
// request.GetSignalRHelper().MissCall(request.CallSid, voipCall.AnsweredBy.ToString());
// voipEngine.SaveAdditionalInfo(voipCall.Id);
// }
// private VoipCall CallFromTwilioRequest(TwilioVoiceRequest request)
// {
// if (!string.IsNullOrEmpty(request.DialCallSid))
// {
// return new VoipCall
// {
// Id = request.DialCallSid,
// ParentID = request.CallSid,
// From = request.From,
// To = request.To,
// AnsweredBy = request.CallerId,
// EndDialDate = DateTime.UtcNow
// };
// }
// return new VoipCall
// {
// Id = request.CallSid,
// ParentID = request.ParentCallSid,
// From = request.From,
// To = request.To,
// AnsweredBy = request.CallerId,
// Date = DateTime.UtcNow,
// ContactId = request.ContactId
// };
// }
// private HttpResponseMessage GetHttpResponse(VoiceResponse response)
// {
// Log.Info(response);
// return new HttpResponseMessage { Content = new StringContent(response.ToString(), Encoding.UTF8, "application/xml") };
// }
// }
// [Scope]
// public class TwilioVoiceRequest : VoiceRequest
// {
// public TwilioVoiceRequest(TwilioResponseHelper twilioResponseHelper,
// CommonLinkUtility commonLinkUtility,
// DaoFactory daoFactory,
// SecurityContext securityContext,
// CRMSecurity crmSecurity,
// VoipEngine voipEngine,
// SignalrServiceClient signalrServiceClient)
// {
// DaoFactory = daoFactory;
// CommonLinkUtility = commonLinkUtility;
// TwilioResponseHelper = twilioResponseHelper;
// SecurityContext = securityContext;
// CRMSecurity = crmSecurity;
// VoipEngine = voipEngine;
// SignalrServiceClient = signalrServiceClient;
// }
// public SignalrServiceClient SignalrServiceClient { get; }
// public VoipEngine VoipEngine { get; }
// public CRMSecurity CRMSecurity { get; }
// public TwilioResponseHelper TwilioResponseHelper { get; }
// public CommonLinkUtility CommonLinkUtility { get; }
// public DaoFactory DaoFactory { get; }
// public SecurityContext SecurityContext { get; }
// public Guid CallerId { get; set; }
// public int ContactId { get; set; }
// public string ParentCallSid { get; set; }
// public string QueueResult { get; set; }
// public string QueueTime { get; set; }
// public string QueueSid { get; set; }
// public bool Reject { get; set; }
// public string RedirectTo { get; set; }
// public string CurrentQueueSize { get; set; }
// public bool Pause { get { return GetSettings().Pause; } }
// private TwilioResponseHelper GetTwilioResponseHelper()
// {
// return TwilioResponseHelper;
// }
// private VoipSettings settings;
// private VoipSettings GetSettings()
// {
// return settings ?? (settings = DaoFactory.GetVoipDao().GetNumber(IsInbound ? To : From).Settings);
// }
// private SignalRHelper signalRHelper;
// public SignalRHelper GetSignalRHelper()
// {
// return signalRHelper ?? (signalRHelper = new SignalRHelper(IsInbound ? To : From, SignalrServiceClient));
// }
// public bool IsInbound
// {
// get { return Direction == "inbound"; }
// }
// public void AddAdditionalFields(Guid? callerId, int contactId = 0, string reject = null, string redirectTo = null)
// {
// if (callerId.HasValue && !callerId.Value.Equals(ASC.Core.Configuration.Constants.Guest.ID))
// {
// CallerId = callerId.Value;
// SecurityContext.AuthenticateMe(CallerId);
// }
// if (contactId != 0)
// {
// ContactId = contactId;
// }
// if (!string.IsNullOrEmpty(reject))
// {
// Reject = Convert.ToBoolean(reject);
// }
// if (!string.IsNullOrEmpty(redirectTo))
// {
// RedirectTo = redirectTo;
// }
// }
// internal VoiceResponse Inbound(VoipCall call, DaoFactory daoFactory)
// {
// var contactPhone = call.Status == VoipCallStatus.Incoming || call.Status == VoipCallStatus.Answered
// ? call.From
// : call.To;
// Contact contact;
// var contacts = VoipEngine.GetContacts(contactPhone, daoFactory);
// var managers = contacts.SelectMany(CRMSecurity.GetAccessSubjectGuidsTo).ToList();
// var agent = GetSignalRHelper().GetAgent(managers);
// if (agent != null && agent.Item1 != null)
// {
// var agentId = agent.Item1.Id;
// SecurityContext.AuthenticateMe(agentId);
// call.AnsweredBy = agentId;
// contact = contacts.FirstOrDefault(CRMSecurity.CanAccessTo);
// DaoFactory.GetVoipDao().SaveOrUpdateCall(call);
// }
// else
// {
// contact = contacts.FirstOrDefault();
// }
// if (contact == null)
// {
// contact = VoipEngine.CreateContact(call.From.TrimStart('+'));
// call.ContactId = contact.ID;
// DaoFactory.GetVoipDao().SaveOrUpdateCall(call);
// }
// return GetTwilioResponseHelper().Inbound(agent);
// }
// internal VoiceResponse Outbound() { return GetTwilioResponseHelper().Outbound(); }
// internal VoiceResponse Dial() { return GetTwilioResponseHelper().Dial(); }
// internal VoiceResponse Enqueue(string queueResult) { return GetTwilioResponseHelper().Enqueue(queueResult); }
// internal VoiceResponse Queue() { return GetTwilioResponseHelper().Queue(); }
// internal VoiceResponse Leave() { return GetTwilioResponseHelper().Leave(); }
// internal VoiceResponse Dequeue() { return GetTwilioResponseHelper().Dequeue(); }
// internal VoiceResponse Wait() { return GetTwilioResponseHelper().Wait(QueueSid, QueueTime, QueueTime); }
// internal VoiceResponse GatherQueue() { return GetTwilioResponseHelper().GatherQueue(Digits, To.Substring(1), new List<Agent>()); }
// internal VoiceResponse Redirect() { return GetTwilioResponseHelper().Redirect(RedirectTo); }
// internal VoiceResponse VoiceMail() { return GetTwilioResponseHelper().VoiceMail(); }
// }
// [Scope]
// public class ValidateRequestFilter : ActionFilterAttribute
// {
// public ValidateRequestFilter(ConsumerFactory consumerFactory, IHttpContextAccessor httpContextAccessor)
// {
// ConsumerFactory = consumerFactory;
// HttpContext = httpContextAccessor?.HttpContext;
// }
// public HttpContext HttpContext { get; }
// public ConsumerFactory ConsumerFactory { get; }
// public override void OnActionExecuting(ActionExecutingContext filterContext)
// {
// if (!new RequestValidationHelper().IsValidRequest(filterContext.HttpContext, ConsumerFactory.Get<Web.Core.Sms.TwilioProvider>()["twilioAuthToken"], HttpContext.Request.GetUrlRewriter().AbsoluteUri))
// filterContext.Result = new HttpStatusCodeResult(HttpStatusCode.Forbidden);
// base.OnActionExecuting(filterContext);
// }
// }
//}

View File

@ -1,330 +0,0 @@
/*
*
* (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.
*
*/
using System;
using System.Collections.Generic;
using System.Linq;
using ASC.Common;
using ASC.Common.Threading;
using ASC.Core;
using ASC.Core.Tenants;
using ASC.CRM.Core;
using ASC.CRM.Core.Dao;
using ASC.CRM.Core.Entities;
using ASC.CRM.Core.Enums;
using ASC.CRM.Resources;
using ASC.VoipService;
using ASC.VoipService.Dao;
using Microsoft.Extensions.Logging;
namespace ASC.Web.CRM.Classes
{
[Scope]
public class VoipEngine
{
private readonly DistributedTaskQueue _queue;
public readonly DaoFactory _daoFactory;
public readonly VoipDao _voipDao;
public readonly TenantManager _tenantManager;
public readonly ILogger _logger;
public readonly int _tenantId;
public readonly SecurityContext _securityContext;
public readonly TenantUtil _tenantUtil;
public readonly CrmSecurity _crmSecurity;
private readonly object Locker = new object();
public VoipEngine(DaoFactory daoFactory,
CrmSecurity crmSecurity,
TenantUtil tenantUtil,
IDistributedTaskQueueFactory factory,
SecurityContext securityContext,
ILogger logger,
TenantManager tenantManager,
VoipDao voipDao)
{
_crmSecurity = crmSecurity;
_tenantUtil = tenantUtil;
_securityContext = securityContext;
_queue = factory.CreateQueue<QueueItem>();
_logger = logger;
_tenantManager = tenantManager;
_voipDao = voipDao;
_daoFactory = daoFactory;
}
public VoipCall SaveOrUpdateCall(VoipCall callHistory)
{
var dao = _daoFactory.GetVoipDao();
var call = dao.GetCall(callHistory.Id) ?? callHistory;
if (string.IsNullOrEmpty(call.ParentCallId))
{
GetContact(call);
}
if (!callHistory.AnsweredBy.Equals(Guid.Empty))
{
call.AnsweredBy = callHistory.AnsweredBy;
}
if (!callHistory.Date.Equals(default(DateTime)))
{
call.Date = callHistory.Date;
}
if (!callHistory.EndDialDate.Equals(default(DateTime)))
{
call.EndDialDate = callHistory.EndDialDate;
}
if (call.Price == 0 && callHistory.Price != default(decimal))
{
call.Price = callHistory.Price;
}
if (call.DialDuration == 0)
{
call.DialDuration = callHistory.DialDuration;
}
if (call.VoipRecord == null)
{
call.VoipRecord = new VoipRecord();
}
if (string.IsNullOrEmpty(call.VoipRecord.Sid))
{
call.VoipRecord.Sid = callHistory.VoipRecord.Sid;
}
if (call.VoipRecord.Price == default(decimal))
{
call.VoipRecord.Price = callHistory.VoipRecord.Price;
}
if (string.IsNullOrEmpty(call.VoipRecord.Uri))
{
call.VoipRecord.Uri = callHistory.VoipRecord.Uri;
}
if (call.VoipRecord.Duration == 0)
{
call.VoipRecord.Duration = callHistory.VoipRecord.Duration;
}
if (callHistory.Status.HasValue)
{
call.Status = callHistory.Status;
}
return dao.SaveOrUpdateCall(call);
}
public void AddHistoryToCallContact(VoipCall call, DaoFactory daoFactory)
{
var listItemDao = daoFactory.GetListItemDao();
if (call == null || call.ContactId == 0) return;
var category = listItemDao.GetByTitle(ListType.HistoryCategory, CRMCommonResource.HistoryCategory_Call);
if (category == null)
{
category = new ListItem(CRMCommonResource.HistoryCategory_Call, "event_category_call.png");
category.ID = listItemDao.CreateItem(ListType.HistoryCategory, category);
}
var contact = daoFactory.GetContactDao().GetByID(call.ContactId);
if (contact != null && _crmSecurity.CanAccessTo(contact))
{
var note = call.Status == VoipCallStatus.Incoming || call.Status == VoipCallStatus.Answered
? CRMContactResource.HistoryVoipIncomingNote
: CRMContactResource.HistoryVoipOutcomingNote;
var content = string.Format(note, call.DialDuration);
var relationshipEvent = new RelationshipEvent
{
CategoryID = category.ID,
EntityType = EntityType.Any,
EntityID = 0,
Content = content,
ContactID = contact.ID,
CreateOn = _tenantUtil.DateTimeFromUtc(DateTime.UtcNow),
CreateBy = _securityContext.CurrentAccount.ID
};
daoFactory.GetRelationshipEventDao().CreateItem(relationshipEvent);
}
}
public Contact GetContact(VoipCall call)
{
if (call.ContactId != 0)
{
return null;
}
var contactPhone = call.Status == VoipCallStatus.Incoming || call.Status == VoipCallStatus.Answered ? call.NumberFrom : call.NumberTo;
var newContactIds = _daoFactory.GetContactDao().GetContactIDsByContactInfo(ContactInfoType.Phone, contactPhone.TrimStart('+'), null, true);
foreach (var newContactId in newContactIds)
{
if (newContactId != 0)
{
var existContact = _daoFactory.GetContactDao().GetByID(newContactId);
if (_crmSecurity.CanAccessTo(existContact))
{
call.ContactId = newContactId;
return existContact;
}
}
}
return null;
}
public List<Contact> GetContacts(string contactPhone, DaoFactory daoFactory)
{
var dao = daoFactory.GetContactDao();
var ids = dao.GetContactIDsByContactInfo(ContactInfoType.Phone, contactPhone.TrimStart('+'), null, true);
return ids.Select(r => dao.GetByID(r)).ToList();
}
public void SaveAdditionalInfo(string callId)
{
lock (Locker)
{
var _queueItem = new QueueItem { CallID = callId, TenantID = _tenantId };
_queue.EnqueueTask((a, b) => SaveAdditionalInfoAction(_queueItem), _queueItem); ;
}
}
private void SaveAdditionalInfoAction(QueueItem queueItem)
{
try
{
_tenantManager.SetCurrentTenant(queueItem.TenantID);
var voipEngine = new VoipEngine(_daoFactory,
_crmSecurity,
_tenantUtil,
null,
_securityContext,
null,
_tenantManager,
_voipDao);
var dao = _daoFactory.GetVoipDao();
var call = dao.GetCall(queueItem.CallID);
GetPriceAndDuration(call);
if (call.ChildCalls.Any())
{
call.ChildCalls.ForEach(r =>
{
GetPriceAndDuration(r);
voipEngine.SaveOrUpdateCall(r);
});
}
call = voipEngine.SaveOrUpdateCall(call);
if (!string.IsNullOrEmpty(call.VoipRecord.Sid))
{
call.VoipRecord = _voipDao.GetProvider().GetRecord((string)call.Id, (string)call.VoipRecord.Sid);
voipEngine.SaveOrUpdateCall(call);
}
_securityContext.AuthenticateMeWithoutCookie(call.AnsweredBy);
AddHistoryToCallContact(call, _daoFactory);
}
catch (Exception ex)
{
_logger.LogError("SaveAdditionalInfo {0}, {1}", ex, ex.StackTrace);
}
}
private void GetPriceAndDuration(VoipCall call)
{
var provider = _voipDao.GetProvider();
var twilioCall = provider.GetCall(call.Id);
call.Price = twilioCall.Price;
call.DialDuration = twilioCall.DialDuration;
}
public void AnswerCall(VoipCall call)
{
call.AnsweredBy = _securityContext.CurrentAccount.ID;
call.Status = VoipCallStatus.Answered;
_daoFactory.GetVoipDao().SaveOrUpdateCall(call);
}
public Contact CreateContact(string contactPhone)
{
var contact = new Person
{
FirstName = contactPhone,
LastName = _tenantUtil.DateTimeFromUtc(DateTime.UtcNow).ToString("yyyy-MM-dd hh:mm"),
ShareType = ShareType.None,
CreateBy = _securityContext.CurrentAccount.ID,
CreateOn = DateTime.UtcNow
};
contact.ID = _daoFactory.GetContactDao().SaveContact(contact);
_daoFactory.GetContactInfoDao()
.Save(new ContactInfo
{
ContactID = contact.ID,
IsPrimary = true,
InfoType = ContactInfoType.Phone,
Data = contactPhone
});
_crmSecurity.SetAccessTo(contact, new List<Guid> { _securityContext.CurrentAccount.ID });
return contact;
}
private class QueueItem : DistributedTask
{
public int TenantID { get; set; }
public string CallID { get; set; }
}
}
}

View File

@ -1,103 +0,0 @@
/*
*
* (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.
*
*/
using System;
using ASC.CRM.Resources;
using ASC.Web.Core;
using ASC.Web.Core.WebZones;
using ASC.Web.Studio.Core;
namespace ASC.Web.CRM.Configuration
{
[WebZone(WebZoneType.CustomProductList)]
public class VoipModule : IAddon
{
private PathProvider _pathProvider;
private SetupInfo _setupInfo;
public VoipModule(PathProvider pathProvider,
SetupInfo setupInfo)
{
_pathProvider = pathProvider;
_setupInfo = setupInfo;
}
public Guid ID
{
get { return WebItemManager.VoipModuleID; }
}
public string Name
{
get { return CRMVoipResource.VoipModuleTitle; }
}
public string Description
{
get { return CRMVoipResource.VoipModuleDescription; }
}
public string StartURL
{
get { return _pathProvider.StartURL() + "settings.aspx?type=voip.common&sysname=/modules/voip"; }
}
public string HelpURL
{
get { return null; }
}
public string ProductClassName { get { return "voip"; } }
public bool Visible { get { return _setupInfo.VoipEnabled; } }
public AddonContext Context { get; private set; }
public void Init()
{
Context = new AddonContext
{
DefaultSortOrder = 90,
IconFileName = "voip_logo.png",
CanNotBeDisabled = true
};
}
public void Shutdown()
{
}
WebItemContext IWebItem.Context
{
get { return Context; }
}
public string ApiURL => throw new NotImplementedException();
}
}

View File

@ -1,3 +1,29 @@
// (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
/*
*
* (c) Copyright Ascensio System Limited 2010-2018
@ -26,7 +52,6 @@
using System;
using ASC.Common;
using ASC.VoipService.Dao;
using Microsoft.Extensions.DependencyInjection;
@ -152,11 +177,6 @@ namespace ASC.CRM.Core.Dao
{
return ServiceProvider.GetService<InvoiceLineDao>();
}
public VoipDao GetVoipDao()
{
return ServiceProvider.GetService<VoipDao>();
}
}
public class DaoFactoryExtension
@ -191,32 +211,31 @@ namespace ASC.CRM.Core.Dao
}
}
}
//TaskDao
//ListItemDao
//ContactDao
//CustomFieldDao
//DealDao
//DealMilestoneDao
//TagDao
//SearchDao
//RelationshipEventDao
//FileDao
//CasesDao
//TaskTemplateContainerDao
//TaskTemplateDao
//ReportDao
//CurrencyRateDao
//CurrencyInfoDao
//ContactInfoDao
//InvoiceDao
//InvoiceItemDao
//InvoiceTaxDao
//InvoiceLineDao
//VoipDao
}
//TaskDao
//ListItemDao
//ContactDao
//CustomFieldDao
//DealDao
//DealMilestoneDao
//TagDao
//SearchDao
//RelationshipEventDao
//FileDao
//CasesDao
//TaskTemplateContainerDao
//TaskTemplateDao
//ReportDao
//CurrencyRateDao
//CurrencyInfoDao
//ContactInfoDao
//InvoiceDao
//InvoiceItemDao
//InvoiceTaxDao
//InvoiceLineDao

View File

@ -1,3 +1,29 @@
// (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
/*
*
* (c) Copyright Ascensio System Limited 2010-2018
@ -45,7 +71,6 @@ using ASC.CRM.Core.Entities;
using ASC.CRM.Core.Enums;
using ASC.CRM.Resources;
using ASC.Files.Core;
using ASC.VoipService;
using ASC.Web.Core.Users;
using ASC.Web.CRM.Classes;
@ -66,15 +91,15 @@ namespace ASC.CRM.Core.Dao
const string TimeFormat = "[h]:mm:ss;@";
const string ShortDateFormat = "M/d/yyyy";
private IServiceProvider _serviceProvider;
private TenantManager _tenantManager;
private UserManager _userManager;
private Global _global;
private CurrencyInfo _defaultCurrency;
private TenantUtil _tenantUtil;
private DaoFactory _daoFactory;
private IDaoFactory _daoFilesFactory;
private DisplayUserSettingsHelper _displayUserSettings;
private readonly IServiceProvider _serviceProvider;
private readonly TenantManager _tenantManager;
private readonly UserManager _userManager;
private readonly Global _global;
private readonly CurrencyInfo _defaultCurrency;
private readonly TenantUtil _tenantUtil;
private readonly DaoFactory _daoFactory;
private readonly IDaoFactory _daoFilesFactory;
private readonly DisplayUserSettingsHelper _displayUserSettings;
#region Constructor
@ -1664,123 +1689,6 @@ namespace ASC.CRM.Core.Dao
#endregion
#region GetWorkloadByViopReport
public bool CheckWorkloadByViopReportData(ReportTimePeriod timePeriod, Guid[] managers)
{
DateTime fromDate;
DateTime toDate;
GetTimePeriod(timePeriod, out fromDate, out toDate);
return Query(CrmDbContext.VoipCalls)
.Where(x => x.ParentCallId == "")
.Where(x => managers != null && managers.Any() ? managers.ToList().Contains(x.AnsweredBy) : true)
.Where(x => timePeriod == ReportTimePeriod.DuringAllTime ?
true :
x.DialDate >= _tenantUtil.DateTimeToUtc(fromDate) && x.DialDate <= _tenantUtil.DateTimeToUtc(toDate))
.Any();
}
public object GetWorkloadByViopReportData(ReportTimePeriod timePeriod, Guid[] managers)
{
var reportData = BuildWorkloadByViopReport(timePeriod, managers);
return reportData == null || !reportData.Any() ? null : GenerateReportData(timePeriod, reportData);
}
private List<WorkloadByViop> BuildWorkloadByViopReport(ReportTimePeriod timePeriod, Guid[] managers)
{
DateTime fromDate;
DateTime toDate;
GetTimePeriod(timePeriod, out fromDate, out toDate);
var result = Query(CrmDbContext.VoipCalls)
.Where(x => x.ParentCallId == "")
.Where(x => managers != null && managers.Any() ? managers.Contains(x.AnsweredBy) : true)
.Where(x => timePeriod == ReportTimePeriod.DuringAllTime ? true : x.DialDate >= _tenantUtil.DateTimeToUtc(fromDate) && x.DialDate <= _tenantUtil.DateTimeToUtc(toDate))
.GroupBy(x => new { x.AnsweredBy, x.Status })
.Select(x => new
{
answered_by = x.Key.AnsweredBy,
status = x.Key.Status,
calls_count = x.Count(),
duration = x.Sum(x => x.DialDuration)
})
.ToList()
.ConvertAll(x => new WorkloadByViop
{
UserId = x.answered_by,
UserName = _displayUserSettings.GetFullUserName(x.answered_by),
Status = x.status,
Count = x.calls_count,
Duration = x.duration ?? x.duration.Value
});
return result;
}
private WorkloadByViop ToWorkloadByViop(object[] row)
{
return new WorkloadByViop
{
UserId = string.IsNullOrEmpty(Convert.ToString(row[0])) ? Guid.Empty : new Guid(Convert.ToString(row[0])),
UserName = Convert.ToString(row[1] ?? string.Empty),
Status = (VoipCallStatus)Convert.ToInt32(row[2] ?? 0),
Count = Convert.ToInt32(row[3]),
Duration = Convert.ToInt32(row[4])
};
}
private object GenerateReportData(ReportTimePeriod timePeriod, List<WorkloadByViop> data)
{
var reportData = data.Select(item => new List<object>
{
item.UserId,
item.UserName,
(int) item.Status,
item.Count,
new {format = TimeFormat, value = SecondsToTimeFormat(item.Duration)}
}).ToList();
return new
{
resource = new
{
header = CRMReportResource.WorkloadByVoipReport,
sheetName = CRMReportResource.WorkloadByVoipReport,
dateRangeLabel = CRMReportResource.TimePeriod + ":",
dateRangeValue = GetTimePeriodText(timePeriod),
chartName = CRMReportResource.CallsCount,
chartName1 = CRMReportResource.CallsDuration,
header1 = CRMReportResource.CallsCount,
header2 = CRMReportResource.CallsDuration,
manager = CRMReportResource.Manager,
total = CRMReportResource.Total,
incoming = CRMReportResource.Incoming,
outcoming = CRMReportResource.Outcoming,
timeFormat = TimeFormat
},
data = reportData
};
}
private string SecondsToTimeFormat(int duration)
{
var timeSpan = TimeSpan.FromSeconds(duration);
return $"{(timeSpan.TotalHours < 10 ? "0" : "") + (int)timeSpan.TotalHours}:{(timeSpan.Minutes < 10 ? "0" : "") + timeSpan.Minutes}:{(timeSpan.Seconds < 10 ? "0" : "") + timeSpan.Seconds}";
}
#endregion
#region SummaryForThePeriodReport
public bool CheckSummaryForThePeriodReportData(ReportTimePeriod timePeriod, Guid[] managers)
@ -1832,20 +1740,12 @@ namespace ASC.CRM.Core.Dao
.Where(x => x.CreateOn >= _tenantUtil.DateTimeToUtc(fromDate) && x.CreateOn <= _tenantUtil.DateTimeToUtc(toDate))
.Any();
var voipSqlQuery = Query(CrmDbContext.VoipCalls)
.Where(x => x.ParentCallId == "")
.Where(x => managers != null && managers.Any() ? managers.Contains(x.AnsweredBy) : true)
.Where(x => x.DialDate >= _tenantUtil.DateTimeToUtc(fromDate) && x.DialDate <= _tenantUtil.DateTimeToUtc(toDate))
.Any();
return newDealsSqlQuery ||
closedDealsSqlQuery ||
overdueDealsSqlQuery ||
invoicesSqlQuery ||
contactsSqlQuery ||
tasksSqlQuery ||
voipSqlQuery;
tasksSqlQuery;
}
public object GetSummaryForThePeriodReportData(ReportTimePeriod timePeriod, Guid[] managers, string defaultCurrency)
@ -2000,20 +1900,8 @@ namespace ASC.CRM.Core.Dao
})
.OrderBy(x => x.title)
.ToList();
// .OrderBy("i.sort_order, i.title", true);
// .OrderBy("i.sort_order, i.title", true);
var voipSqlQuery = Query(CrmDbContext.VoipCalls)
.Where(x => String.IsNullOrEmpty(x.ParentCallId))
.Where(x => managers != null && managers.Any() ? managers.Contains(x.AnsweredBy) : true)
.Where(x => x.DialDate >= _tenantUtil.DateTimeToUtc(fromDate) && x.DialDate <= _tenantUtil.DateTimeToUtc(toDate))
.GroupBy(x => x.Status)
.Select(x => new
{
status = x.Key,
calls_count = x.Count(),
duration = x.Sum(x => x.DialDuration)
})
.ToList();
return new
{
DealsInfo = new
@ -2025,8 +1913,7 @@ namespace ASC.CRM.Core.Dao
},
InvoicesInfo = invoicesSqlQuery,
ContactsInfo = contactsSqlQuery,
TasksInfo = tasksSqlQuery,
VoipInfo = voipSqlQuery
TasksInfo = tasksSqlQuery
};
}

View File

@ -1,4 +1,30 @@
using ASC.Common;
// (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
using ASC.Common;
using ASC.Core.Common.EF;
using ASC.Core.Common.EF.Model;
@ -33,8 +59,6 @@ namespace ASC.CRM.Core.EF
public virtual DbSet<DbTaskTemplate> TaskTemplates { get; set; }
public virtual DbSet<DbTaskTemplateContainer> TaskTemplateContainer { get; set; }
public virtual DbSet<DbTaskTemplateTask> TaskTemplateTask { get; set; }
public virtual DbSet<DbVoipCalls> VoipCalls { get; set; }
public virtual DbSet<DbVoipNumber> VoipNumber { get; set; }
public virtual DbSet<DbTenant> Tenants { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
@ -47,8 +71,8 @@ namespace ASC.CRM.Core.EF
.AddDbRelationshipEvent()
.AddDbDeal()
.AddDbTask()
.AddDbTenant();
.AddDbTenant();
modelBuilder.Entity<DbCurrencyInfo>(entity =>
{
entity.HasKey(e => e.Abbreviation)
@ -398,66 +422,6 @@ namespace ASC.CRM.Core.EF
.HasName("PRIMARY");
});
modelBuilder.Entity<DbVoipCalls>(entity =>
{
entity.HasIndex(e => e.TenantId)
.HasDatabaseName("tenant_id");
entity.HasIndex(e => new { e.ParentCallId, e.TenantId })
.HasDatabaseName("parent_call_id");
entity.Property(e => e.Id)
.HasCharSet("utf8")
.UseCollation("utf8_general_ci");
entity.Property(e => e.AnsweredBy)
.HasDefaultValueSql("'00000000-0000-0000-0000-000000000000'")
.HasCharSet("utf8")
.UseCollation("utf8_general_ci");
entity.Property(e => e.NumberFrom)
.HasCharSet("utf8")
.UseCollation("utf8_general_ci");
entity.Property(e => e.NumberTo)
.HasCharSet("utf8")
.UseCollation("utf8_general_ci");
entity.Property(e => e.ParentCallId)
.HasCharSet("utf8")
.UseCollation("utf8_general_ci");
entity.Property(e => e.RecordSid)
.HasCharSet("utf8")
.UseCollation("utf8_general_ci");
entity.Property(e => e.RecordUrl)
.HasCharSet("utf8")
.UseCollation("utf8_general_ci");
});
modelBuilder.Entity<DbVoipNumber>(entity =>
{
entity.HasIndex(e => e.TenantId)
.HasDatabaseName("tenant_id");
entity.Property(e => e.Id)
.HasCharSet("utf8")
.UseCollation("utf8_general_ci");
entity.Property(e => e.Alias)
.HasCharSet("utf8")
.UseCollation("utf8_general_ci");
entity.Property(e => e.Number)
.HasCharSet("utf8")
.UseCollation("utf8_general_ci");
entity.Property(e => e.Settings)
.HasCharSet("utf8")
.UseCollation("utf8_general_ci");
});
OnModelCreatingPartial(modelBuilder);
}

View File

@ -1,50 +0,0 @@
// <auto-generated> This file has been auto generated by EF Core Power Tools. </auto-generated>
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using ASC.VoipService;
namespace ASC.CRM.Core.EF
{
[Table("crm_voip_calls")]
public partial class DbVoipCalls : IDbCrm
{
[Key]
[Column("id", TypeName = "varchar(50)")]
public string Id { get; set; }
[Required]
[Column("parent_call_id", TypeName = "varchar(50)")]
public string ParentCallId { get; set; }
[Required]
[Column("number_from", TypeName = "varchar(50)")]
public string NumberFrom { get; set; }
[Required]
[Column("number_to", TypeName = "varchar(50)")]
public string NumberTo { get; set; }
[Column("status", TypeName = "int(10)")]
public VoipCallStatus Status { get; set; }
[Required]
[Column("answered_by", TypeName = "varchar(50)")]
public Guid AnsweredBy { get; set; }
[Column("dial_date", TypeName = "datetime")]
public DateTime? DialDate { get; set; }
[Column("dial_duration", TypeName = "int(11)")]
public int? DialDuration { get; set; }
[Column("record_sid", TypeName = "varchar(50)")]
public string RecordSid { get; set; }
[Column("record_url", TypeName = "text")]
public string RecordUrl { get; set; }
[Column("record_duration", TypeName = "int(11)")]
public int? RecordDuration { get; set; }
[Column("record_price", TypeName = "decimal(10,4)")]
public decimal RecordPrice { get; set; }
[Column("contact_id", TypeName = "int(10)")]
public int? ContactId { get; set; }
[Column("price", TypeName = "decimal(10,4)")]
public decimal? Price { get; set; }
[Column("tenant_id", TypeName = "int(10)")]
public int TenantId { get; set; }
}
}

View File

@ -1,25 +0,0 @@
// <auto-generated> This file has been auto generated by EF Core Power Tools. </auto-generated>
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace ASC.CRM.Core.EF
{
[Table("crm_voip_number")]
public partial class DbVoipNumber
{
[Key]
[Column("id", TypeName = "varchar(50)")]
public string Id { get; set; }
[Required]
[Column("number", TypeName = "varchar(50)")]
public string Number { get; set; }
[Column("alias", TypeName = "varchar(255)")]
public string Alias { get; set; }
[Column("settings", TypeName = "text")]
public string Settings { get; set; }
[Column("tenant_id", TypeName = "int(10)")]
public int TenantId { get; set; }
}
}

View File

@ -1,3 +1,29 @@
// (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
/*
*
* (c) Copyright Ascensio System Limited 2010-2018
@ -29,7 +55,6 @@
using System;
using ASC.CRM.Core.Enums;
using ASC.VoipService;
#endregion
@ -87,15 +112,6 @@ namespace ASC.CRM.Core.Entities
public int OverdueCount { get; set; }
}
public class WorkloadByViop
{
public Guid UserId { get; set; }
public string UserName { get; set; }
public VoipCallStatus Status { get; set; }
public int Count { get; set; }
public int Duration { get; set; }
}
public class WorkloadByContacts
{
public int CategoryId { get; set; }

View File

@ -1,3 +1,29 @@
// (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
/*
*
* (c) Copyright Ascensio System Limited 2010-2018
@ -35,7 +61,6 @@ namespace ASC.CRM.Core.Enums
WorkloadByTasks,
WorkloadByDeals,
WorkloadByInvoices,
WorkloadByVoip,
SummaryForThePeriod,
SummaryAtThisMoment
}

View File

@ -1,91 +0,0 @@
/*
*
* (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.
*
*/
using System;
using System.Linq;
using ASC.Api.Core;
using ASC.Common;
using ASC.CRM.ApiModels;
using ASC.CRM.Core.Dao;
using ASC.VoipService;
using ASC.Web.Api.Models;
using AutoMapper;
namespace ASC.CRM.Mapping
{
[Scope]
public class VoipCallDtoTypeConverter : ITypeConverter<VoipCall, VoipCallDto>
{
private readonly ApiDateTimeHelper _apiDateTimeHelper;
private readonly EmployeeDtoHelper _employeeDtoHelper;
private readonly DaoFactory _daoFactory;
public VoipCallDtoTypeConverter(ApiDateTimeHelper apiDateTimeHelper,
EmployeeDtoHelper employeeDtoHelper,
DaoFactory daoFactory)
{
_daoFactory = daoFactory;
_apiDateTimeHelper = apiDateTimeHelper;
_employeeDtoHelper = employeeDtoHelper;
}
public VoipCallDto Convert(VoipCall source, VoipCallDto destination, ResolutionContext context)
{
if (destination != null)
throw new NotImplementedException();
var result = new VoipCallDto
{
Id = source.Id,
From = source.NumberFrom,
To = source.NumberTo,
Status = source.Status,
AnsweredBy = _employeeDtoHelper.Get(source.AnsweredBy),
DialDate = _apiDateTimeHelper.Get(source.DialDate),
DialDuration = source.DialDuration,
Cost = source.Price + source.ChildCalls.Sum(r => r.Price) + source.VoipRecord.Price,
RecordUrl = source.VoipRecord.Uri,
RecordDuration = source.VoipRecord.Duration
};
if (source.ContactId > 0)
{
result.Contact = context.Mapper.Map<ContactDto>(_daoFactory.GetContactDao().GetByID(source.ContactId));
}
if (source.ChildCalls.Any())
{
result.Calls = source.ChildCalls.Select(childCall => context.Mapper.Map<VoipCallDto>(childCall));
}
return result;
}
}
}

View File

@ -1,847 +0,0 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.42000
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace ASC.CRM.Resources {
using System;
/// <summary>
/// A strongly-typed resource class, for looking up localized strings, etc.
/// </summary>
// This class was auto-generated by the StronglyTypedResourceBuilder
// class via a tool like ResGen or Visual Studio.
// To add or remove a member, edit your .ResX file then rerun ResGen
// with the /str option, or rebuild your VS project.
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
public class CRMVoipResource {
private static global::System.Resources.ResourceManager resourceMan;
private static global::System.Globalization.CultureInfo resourceCulture;
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
internal CRMVoipResource() {
}
/// <summary>
/// Returns the cached ResourceManager instance used by this class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
public static global::System.Resources.ResourceManager ResourceManager {
get {
if (object.ReferenceEquals(resourceMan, null)) {
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("ASC.CRM.Resources.CRMVoipResource", typeof(CRMVoipResource).Assembly);
resourceMan = temp;
}
return resourceMan;
}
}
/// <summary>
/// Overrides the current thread's CurrentUICulture property for all
/// resource lookups using this strongly typed resource class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
public static global::System.Globalization.CultureInfo Culture {
get {
return resourceCulture;
}
set {
resourceCulture = value;
}
}
/// <summary>
/// Looks up a localized string similar to Добавить оператора.
/// </summary>
public static string AddOperatorBtn {
get {
return ResourceManager.GetString("AddOperatorBtn", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Добавить операторов.
/// </summary>
public static string AddOperatorsBtn {
get {
return ResourceManager.GetString("AddOperatorsBtn", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Добавить мелодию.
/// </summary>
public static string AddRingtoneBtn {
get {
return ResourceManager.GetString("AddRingtoneBtn", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Псевдоним.
/// </summary>
public static string Alias {
get {
return ResourceManager.GetString("Alias", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to {0}Псевдоним{1} &quot;дальше идет объяснительный текст&quot;.
/// </summary>
public static string AliasDscrMsg {
get {
return ResourceManager.GetString("AliasDscrMsg", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Введите название для номера.
/// </summary>
public static string AliasPlaceholder {
get {
return ResourceManager.GetString("AliasPlaceholder", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Buy phone number.
/// </summary>
public static string BuyNumberBtn {
get {
return ResourceManager.GetString("BuyNumberBtn", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Покупка номера.
/// </summary>
public static string BuyNumberHeader {
get {
return ResourceManager.GetString("BuyNumberHeader", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Call.
/// </summary>
public static string Call {
get {
return ResourceManager.GetString("Call", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Agent.
/// </summary>
public static string CallAgent {
get {
return ResourceManager.GetString("CallAgent", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Client.
/// </summary>
public static string CallClient {
get {
return ResourceManager.GetString("CallClient", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Cost.
/// </summary>
public static string CallCost {
get {
return ResourceManager.GetString("CallCost", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Date/Time.
/// </summary>
public static string CallDatetime {
get {
return ResourceManager.GetString("CallDatetime", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Duration.
/// </summary>
public static string CallDuration {
get {
return ResourceManager.GetString("CallDuration", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Type.
/// </summary>
public static string CallType {
get {
return ResourceManager.GetString("CallType", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Waiting Time.
/// </summary>
public static string CallWaitingTime {
get {
return ResourceManager.GetString("CallWaitingTime", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Отмена.
/// </summary>
public static string CancelBtn {
get {
return ResourceManager.GetString("CancelBtn", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Удалить.
/// </summary>
public static string DeleteBtn {
get {
return ResourceManager.GetString("DeleteBtn", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Номер сохранится в twilio, но будет недоступен в рамках текущего портала.
/// </summary>
public static string DeleteNumberBody {
get {
return ResourceManager.GetString("DeleteNumberBody", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Удалить номер.
/// </summary>
public static string DeleteNumberBtn {
get {
return ResourceManager.GetString("DeleteNumberBtn", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Удалить номер.
/// </summary>
public static string DeleteNumberHeader {
get {
return ResourceManager.GetString("DeleteNumberHeader", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Удалить мелодию.
/// </summary>
public static string DeleteRingtoneBtn {
get {
return ResourceManager.GetString("DeleteRingtoneBtn", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Редактировать.
/// </summary>
public static string EditBtn {
get {
return ResourceManager.GetString("EditBtn", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Enter Credentials.
/// </summary>
public static string EmptyScreenEnter {
get {
return ResourceManager.GetString("EmptyScreenEnter", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to IP Telephony Setup.
/// </summary>
public static string EmptyScreenHeader {
get {
return ResourceManager.GetString("EmptyScreenHeader", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Buy a new IP phone number to add it to the ONLYOFFICE portal. Once added you can use this phone number with portal CRM.
///.
/// </summary>
public static string EmptyScreenNumberDescription1 {
get {
return ResourceManager.GetString("EmptyScreenNumberDescription1", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Note: the phone numbers you already have at Twilio website cannot be transferred to the portal..
/// </summary>
public static string EmptyScreenNumberDescription2 {
get {
return ResourceManager.GetString("EmptyScreenNumberDescription2", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to No IP telephony numbers have been added yet.
/// </summary>
public static string EmptyScreenNumberHeader {
get {
return ResourceManager.GetString("EmptyScreenNumberHeader", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Register Account.
/// </summary>
public static string EmptyScreenRegister {
get {
return ResourceManager.GetString("EmptyScreenRegister", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Click the &apos;Register Account&apos; button to go to Twilio website for registration to be able to use the IP telephony feature..
/// </summary>
public static string EmptyScreenText1 {
get {
return ResourceManager.GetString("EmptyScreenText1", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to If you already have a Twilio account, enter the API credentials: Account SID and Auth token, which can be found at the {0}settings{1} page..
/// </summary>
public static string EmptyScreenText2 {
get {
return ResourceManager.GetString("EmptyScreenText2", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Enter Credentials.
/// </summary>
public static string EnterCredentialsHeader {
get {
return ResourceManager.GetString("EnterCredentialsHeader", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Общие настройки.
/// </summary>
public static string GeneralSettings {
get {
return ResourceManager.GetString("GeneralSettings", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Мелодии приветствия.
/// </summary>
public static string GreetingRingtones {
get {
return ResourceManager.GetString("GreetingRingtones", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Incoming Call.
/// </summary>
public static string IncomingCall {
get {
return ResourceManager.GetString("IncomingCall", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to {0}Очередь входящих звонков{1} &quot;дальше идет объяснительный текст&quot;.
/// </summary>
public static string IncomingCallsQueueDscrMsg {
get {
return ResourceManager.GetString("IncomingCallsQueueDscrMsg", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Размер очереди входящих звонков.
/// </summary>
public static string IncomingCallsQueueSize {
get {
return ResourceManager.GetString("IncomingCallsQueueSize", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to После привязки все вызовы будут обрабатываться текущим порталом..
/// </summary>
public static string LinkNumberBody {
get {
return ResourceManager.GetString("LinkNumberBody", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Привязать купленный номер.
/// </summary>
public static string LinkNumberBtn {
get {
return ResourceManager.GetString("LinkNumberBtn", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Привязка номера.
/// </summary>
public static string LinkNumberHeader {
get {
return ResourceManager.GetString("LinkNumberHeader", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Номер успешно привязан.
/// </summary>
public static string LinkNumberSuccessMsg {
get {
return ResourceManager.GetString("LinkNumberSuccessMsg", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Идет загрузка, пожалуйста подождите.
/// </summary>
public static string LoadingMsg {
get {
return ResourceManager.GetString("LoadingMsg", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to К сожалению доступных номеров нет, попробуйте позже..
/// </summary>
public static string NoAvailableNumbersMsg {
get {
return ResourceManager.GetString("NoAvailableNumbersMsg", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to У вас пока нет номеров. Срочно купите!.
/// </summary>
public static string NoExistingNumbersMsg {
get {
return ResourceManager.GetString("NoExistingNumbersMsg", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to У вас нет номеров. Приобрести номер можно {0}здесь{1}..
/// </summary>
public static string NoNumbersMsg {
get {
return ResourceManager.GetString("NoNumbersMsg", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Нет номеров с такими крутыми циферками.
/// </summary>
public static string NoSearchingNumbersMsg {
get {
return ResourceManager.GetString("NoSearchingNumbersMsg", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Операторы номера.
/// </summary>
public static string NumberOperators {
get {
return ResourceManager.GetString("NumberOperators", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to {0}Здесь{1} можно их настроить..
/// </summary>
public static string NumbersCountDscrMsg {
get {
return ResourceManager.GetString("NumbersCountDscrMsg", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Количество ваших номеров.
/// </summary>
public static string NumbersCountMsg {
get {
return ResourceManager.GetString("NumbersCountMsg", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Оператор.
/// </summary>
public static string Operator {
get {
return ResourceManager.GetString("Operator", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Пауза оператора.
/// </summary>
public static string OperatorPause {
get {
return ResourceManager.GetString("OperatorPause", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Выключена.
/// </summary>
public static string OperatorPauseDisabled {
get {
return ResourceManager.GetString("OperatorPauseDisabled", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to {0}Пауза оператора{1} &quot;дальше идет объяснительный текст&quot;.
/// </summary>
public static string OperatorPauseDscrMsg {
get {
return ResourceManager.GetString("OperatorPauseDscrMsg", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Включена.
/// </summary>
public static string OperatorPauseEnabled {
get {
return ResourceManager.GetString("OperatorPauseEnabled", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Исходящие звонки.
/// </summary>
public static string OutgoingCalls {
get {
return ResourceManager.GetString("OutgoingCalls", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Мелодии очереди.
/// </summary>
public static string QueueRingtones {
get {
return ResourceManager.GetString("QueueRingtones", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Быстрая настройка.
/// </summary>
public static string QuickTuning {
get {
return ResourceManager.GetString("QuickTuning", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to {0}Быстрая настройка{1} &quot;дальше идет объяснительный текст&quot;.
/// </summary>
public static string QuickTuningDscrMsg {
get {
return ResourceManager.GetString("QuickTuningDscrMsg", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Запись звонков.
/// </summary>
public static string RecordingCalls {
get {
return ResourceManager.GetString("RecordingCalls", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Записи разговоров хранятся в формате WAV. Ваш браузер не поддерживает воспроизведение аудиофайлов в этом формате, поэтому Вы не сможете прослушать свои записи..
/// </summary>
public static string RecordingsCallsPlayNotSupportedMsg {
get {
return ResourceManager.GetString("RecordingsCallsPlayNotSupportedMsg", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Список браузеров, поддерживающих данную функцию можно найти {0}здесь{1}.
/// </summary>
public static string RecordingsCallsPlayNotSupportedTipMsg {
get {
return ResourceManager.GetString("RecordingsCallsPlayNotSupportedTipMsg", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Список мелодий.
/// </summary>
public static string RingtonesList {
get {
return ResourceManager.GetString("RingtonesList", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Настройка мелодий.
/// </summary>
public static string RingtonesTuning {
get {
return ResourceManager.GetString("RingtonesTuning", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to {0}Настройка мелодий{1} &quot;дальше идет объяснительный текст&quot;.
/// </summary>
public static string RingtonesTuningDscrMsg {
get {
return ResourceManager.GetString("RingtonesTuningDscrMsg", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to {0}Рекомендации к загружаемой мелодии{1} Размер файла не должен превышать 5 Mb. Поддерживаемые форматы: mp3..
/// </summary>
public static string RingtonesUploadingRecomendationsMsg {
get {
return ResourceManager.GetString("RingtonesUploadingRecomendationsMsg", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Поиск.
/// </summary>
public static string SearchLabel {
get {
return ResourceManager.GetString("SearchLabel", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Настройка номера.
/// </summary>
public static string TuningNumber {
get {
return ResourceManager.GetString("TuningNumber", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Account Sid.
/// </summary>
public static string TwilioAccountSid {
get {
return ResourceManager.GetString("TwilioAccountSid", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Auth Token.
/// </summary>
public static string TwilioAuthToken {
get {
return ResourceManager.GetString("TwilioAuthToken", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Не выбрано.
/// </summary>
public static string UnspecifiedOption {
get {
return ResourceManager.GetString("UnspecifiedOption", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Обновить настройки.
/// </summary>
public static string UpdateSettingsBtn {
get {
return ResourceManager.GetString("UpdateSettingsBtn", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Виртуальные номера.
/// </summary>
public static string VirtualNumbers {
get {
return ResourceManager.GetString("VirtualNumbers", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Виртуальные номера и операторы.
/// </summary>
public static string VirtualNumbersAndOperators {
get {
return ResourceManager.GetString("VirtualNumbersAndOperators", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to {0}Виртуальные номера{1} &quot;дальше идет объяснительный текст&quot;.
/// </summary>
public static string VirtualNumbersDscrMsg {
get {
return ResourceManager.GetString("VirtualNumbersDscrMsg", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Голосовая почта.
/// </summary>
public static string Voicemail {
get {
return ResourceManager.GetString("Voicemail", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Мелодии голосового письма.
/// </summary>
public static string VoicemailRingtones {
get {
return ResourceManager.GetString("VoicemailRingtones", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to VoIP.
/// </summary>
public static string VoipModuleDescription {
get {
return ResourceManager.GetString("VoipModuleDescription", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to VoIP.
/// </summary>
public static string VoipModuleTitle {
get {
return ResourceManager.GetString("VoipModuleTitle", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Мелодии ожидания.
/// </summary>
public static string WaitingRingtones {
get {
return ResourceManager.GetString("WaitingRingtones", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Таймаут ожидания.
/// </summary>
public static string WaitingTimeout {
get {
return ResourceManager.GetString("WaitingTimeout", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to 10 минут.
/// </summary>
public static string WaitingTimeout10Minutes {
get {
return ResourceManager.GetString("WaitingTimeout10Minutes", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to 15 минут.
/// </summary>
public static string WaitingTimeout15Minutes {
get {
return ResourceManager.GetString("WaitingTimeout15Minutes", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to 5 минут.
/// </summary>
public static string WaitingTimeout5Minutes {
get {
return ResourceManager.GetString("WaitingTimeout5Minutes", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to {0}Таймаут ожидания{1} &quot;дальше идет объяснительный текст&quot;.
/// </summary>
public static string WaitingTimeoutDscrMsg {
get {
return ResourceManager.GetString("WaitingTimeoutDscrMsg", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Рабочие часы.
/// </summary>
public static string WorkingHours {
get {
return ResourceManager.GetString("WorkingHours", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Некорректный интервал.
/// </summary>
public static string WorkingHoursFormatErrorMsg {
get {
return ResourceManager.GetString("WorkingHoursFormatErrorMsg", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Введите время в формате ##:##.
/// </summary>
public static string WorkingHoursFormatTip {
get {
return ResourceManager.GetString("WorkingHoursFormatTip", resourceCulture);
}
}
}
}

View File

@ -1,382 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="AddOperatorBtn" xml:space="preserve">
<value>Добавить оператора</value>
</data>
<data name="AddOperatorsBtn" xml:space="preserve">
<value>Добавить операторов</value>
</data>
<data name="AddRingtoneBtn" xml:space="preserve">
<value>Добавить мелодию</value>
</data>
<data name="Alias" xml:space="preserve">
<value>Псевдоним</value>
</data>
<data name="AliasDscrMsg" xml:space="preserve">
<value>{0}Псевдоним{1} "дальше идет объяснительный текст"</value>
</data>
<data name="AliasPlaceholder" xml:space="preserve">
<value>Введите название для номера</value>
</data>
<data name="BuyNumberBtn" xml:space="preserve">
<value>Buy phone number</value>
</data>
<data name="BuyNumberHeader" xml:space="preserve">
<value>Покупка номера</value>
</data>
<data name="Call" xml:space="preserve">
<value>Call</value>
</data>
<data name="CallAgent" xml:space="preserve">
<value>Agent</value>
</data>
<data name="CallClient" xml:space="preserve">
<value>Client</value>
</data>
<data name="CallCost" xml:space="preserve">
<value>Cost</value>
</data>
<data name="CallDatetime" xml:space="preserve">
<value>Date/Time</value>
</data>
<data name="CallDuration" xml:space="preserve">
<value>Duration</value>
</data>
<data name="CallType" xml:space="preserve">
<value>Type</value>
</data>
<data name="CallWaitingTime" xml:space="preserve">
<value>Waiting Time</value>
</data>
<data name="CancelBtn" xml:space="preserve">
<value>Отмена</value>
</data>
<data name="DeleteBtn" xml:space="preserve">
<value>Удалить</value>
</data>
<data name="DeleteNumberBody" xml:space="preserve">
<value>Номер сохранится в twilio, но будет недоступен в рамках текущего портала</value>
</data>
<data name="DeleteNumberBtn" xml:space="preserve">
<value>Удалить номер</value>
</data>
<data name="DeleteNumberHeader" xml:space="preserve">
<value>Удалить номер</value>
</data>
<data name="DeleteRingtoneBtn" xml:space="preserve">
<value>Удалить мелодию</value>
</data>
<data name="EditBtn" xml:space="preserve">
<value>Редактировать</value>
</data>
<data name="EmptyScreenEnter" xml:space="preserve">
<value>Enter Credentials</value>
</data>
<data name="EmptyScreenHeader" xml:space="preserve">
<value>IP Telephony Setup</value>
</data>
<data name="EmptyScreenNumberDescription1" xml:space="preserve">
<value>Buy a new IP phone number to add it to the ONLYOFFICE portal. Once added you can use this phone number with portal CRM.
</value>
</data>
<data name="EmptyScreenNumberDescription2" xml:space="preserve">
<value>Note: the phone numbers you already have at Twilio website cannot be transferred to the portal.</value>
</data>
<data name="EmptyScreenNumberHeader" xml:space="preserve">
<value>No IP telephony numbers have been added yet</value>
</data>
<data name="EmptyScreenRegister" xml:space="preserve">
<value>Register Account</value>
</data>
<data name="EmptyScreenText1" xml:space="preserve">
<value>Click the 'Register Account' button to go to Twilio website for registration to be able to use the IP telephony feature.</value>
</data>
<data name="EmptyScreenText2" xml:space="preserve">
<value>If you already have a Twilio account, enter the API credentials: Account SID and Auth token, which can be found at the {0}settings{1} page.</value>
</data>
<data name="EnterCredentialsHeader" xml:space="preserve">
<value>Enter Credentials</value>
</data>
<data name="GeneralSettings" xml:space="preserve">
<value>Общие настройки</value>
</data>
<data name="GreetingRingtones" xml:space="preserve">
<value>Мелодии приветствия</value>
</data>
<data name="IncomingCall" xml:space="preserve">
<value>Incoming Call</value>
</data>
<data name="IncomingCallsQueueDscrMsg" xml:space="preserve">
<value>{0}Очередь входящих звонков{1} "дальше идет объяснительный текст"</value>
</data>
<data name="IncomingCallsQueueSize" xml:space="preserve">
<value>Размер очереди входящих звонков</value>
</data>
<data name="LinkNumberBody" xml:space="preserve">
<value>После привязки все вызовы будут обрабатываться текущим порталом.</value>
</data>
<data name="LinkNumberBtn" xml:space="preserve">
<value>Привязать купленный номер</value>
</data>
<data name="LinkNumberHeader" xml:space="preserve">
<value>Привязка номера</value>
</data>
<data name="LinkNumberSuccessMsg" xml:space="preserve">
<value>Номер успешно привязан</value>
</data>
<data name="LoadingMsg" xml:space="preserve">
<value>Идет загрузка, пожалуйста подождите</value>
</data>
<data name="NoAvailableNumbersMsg" xml:space="preserve">
<value>К сожалению доступных номеров нет, попробуйте позже.</value>
</data>
<data name="NoExistingNumbersMsg" xml:space="preserve">
<value>У вас пока нет номеров. Срочно купите!</value>
</data>
<data name="NoNumbersMsg" xml:space="preserve">
<value>У вас нет номеров. Приобрести номер можно {0}здесь{1}.</value>
</data>
<data name="NoSearchingNumbersMsg" xml:space="preserve">
<value>Нет номеров с такими крутыми циферками</value>
</data>
<data name="NumberOperators" xml:space="preserve">
<value>Операторы номера</value>
</data>
<data name="NumbersCountDscrMsg" xml:space="preserve">
<value>{0}Здесь{1} можно их настроить.</value>
</data>
<data name="NumbersCountMsg" xml:space="preserve">
<value>Количество ваших номеров</value>
</data>
<data name="Operator" xml:space="preserve">
<value>Оператор</value>
</data>
<data name="OperatorPause" xml:space="preserve">
<value>Пауза оператора</value>
</data>
<data name="OperatorPauseDisabled" xml:space="preserve">
<value>Выключена</value>
</data>
<data name="OperatorPauseDscrMsg" xml:space="preserve">
<value>{0}Пауза оператора{1} "дальше идет объяснительный текст"</value>
</data>
<data name="OperatorPauseEnabled" xml:space="preserve">
<value>Включена</value>
</data>
<data name="OutgoingCalls" xml:space="preserve">
<value>Исходящие звонки</value>
</data>
<data name="QueueRingtones" xml:space="preserve">
<value>Мелодии очереди</value>
</data>
<data name="QuickTuning" xml:space="preserve">
<value>Быстрая настройка</value>
</data>
<data name="QuickTuningDscrMsg" xml:space="preserve">
<value>{0}Быстрая настройка{1} "дальше идет объяснительный текст"</value>
</data>
<data name="RecordingCalls" xml:space="preserve">
<value>Запись звонков</value>
</data>
<data name="RecordingsCallsPlayNotSupportedMsg" xml:space="preserve">
<value>Записи разговоров хранятся в формате WAV. Ваш браузер не поддерживает воспроизведение аудиофайлов в этом формате, поэтому Вы не сможете прослушать свои записи.</value>
</data>
<data name="RecordingsCallsPlayNotSupportedTipMsg" xml:space="preserve">
<value>Список браузеров, поддерживающих данную функцию можно найти {0}здесь{1}</value>
</data>
<data name="RingtonesList" xml:space="preserve">
<value>Список мелодий</value>
</data>
<data name="RingtonesTuning" xml:space="preserve">
<value>Настройка мелодий</value>
</data>
<data name="RingtonesTuningDscrMsg" xml:space="preserve">
<value>{0}Настройка мелодий{1} "дальше идет объяснительный текст"</value>
</data>
<data name="RingtonesUploadingRecomendationsMsg" xml:space="preserve">
<value>{0}Рекомендации к загружаемой мелодии{1} Размер файла не должен превышать 5 Mb. Поддерживаемые форматы: mp3.</value>
</data>
<data name="SearchLabel" xml:space="preserve">
<value>Поиск</value>
</data>
<data name="TuningNumber" xml:space="preserve">
<value>Настройка номера</value>
</data>
<data name="TwilioAccountSid" xml:space="preserve">
<value>Account Sid</value>
</data>
<data name="TwilioAuthToken" xml:space="preserve">
<value>Auth Token</value>
</data>
<data name="UnspecifiedOption" xml:space="preserve">
<value>Не выбрано</value>
</data>
<data name="UpdateSettingsBtn" xml:space="preserve">
<value>Обновить настройки</value>
</data>
<data name="VirtualNumbers" xml:space="preserve">
<value>Виртуальные номера</value>
</data>
<data name="VirtualNumbersAndOperators" xml:space="preserve">
<value>Виртуальные номера и операторы</value>
</data>
<data name="VirtualNumbersDscrMsg" xml:space="preserve">
<value>{0}Виртуальные номера{1} "дальше идет объяснительный текст"</value>
</data>
<data name="Voicemail" xml:space="preserve">
<value>Голосовая почта</value>
</data>
<data name="VoicemailRingtones" xml:space="preserve">
<value>Мелодии голосового письма</value>
</data>
<data name="VoipModuleDescription" xml:space="preserve">
<value>VoIP</value>
</data>
<data name="VoipModuleTitle" xml:space="preserve">
<value>VoIP</value>
</data>
<data name="WaitingRingtones" xml:space="preserve">
<value>Мелодии ожидания</value>
</data>
<data name="WaitingTimeout" xml:space="preserve">
<value>Таймаут ожидания</value>
</data>
<data name="WaitingTimeout10Minutes" xml:space="preserve">
<value>10 минут</value>
</data>
<data name="WaitingTimeout15Minutes" xml:space="preserve">
<value>15 минут</value>
</data>
<data name="WaitingTimeout5Minutes" xml:space="preserve">
<value>5 минут</value>
</data>
<data name="WaitingTimeoutDscrMsg" xml:space="preserve">
<value>{0}Таймаут ожидания{1} "дальше идет объяснительный текст"</value>
</data>
<data name="WorkingHours" xml:space="preserve">
<value>Рабочие часы</value>
</data>
<data name="WorkingHoursFormatErrorMsg" xml:space="preserve">
<value>Некорректный интервал</value>
</data>
<data name="WorkingHoursFormatTip" xml:space="preserve">
<value>Введите время в формате ##:##</value>
</data>
</root>

View File

@ -1,3 +1,29 @@
// (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
using System.Collections.Generic;
using System.Net.Http;
using System.Text;
@ -60,7 +86,6 @@ namespace ASC.CRM
DIHelper.TryAdd<TasksController>();
DIHelper.TryAdd<TaskTemplateController>();
DIHelper.TryAdd<UtilsController>();
DIHelper.TryAdd<VoIPController>();
DIHelper.TryAdd<CasesDtoTypeConverter>();
DIHelper.TryAdd<ContactDtoTypeConverter>();
@ -74,7 +99,6 @@ namespace ASC.CRM
DIHelper.TryAdd<TaskDtoTypeConverter>();
DIHelper.TryAdd<CustomFieldDtoTypeConverter>();
DIHelper.TryAdd<DealMilestoneDtoTypeConverter>();
DIHelper.TryAdd<VoipCallDtoTypeConverter>();
DIHelper.TryAdd<FactoryIndexerCase>();
DIHelper.TryAdd<FactoryIndexerContact>();

View File

@ -1,364 +0,0 @@
<script id="voip-view-call-tmpl" type="text/x-jquery-tmpl">
<tr class="call-row">
<td class="call-type">
<span class="call-type-icon ${typeClass}"></span>
{{if supportsPlaying && recordUrl}}
<span class="call-type-icon play" data-recordUrl="${recordUrl}"></span>
{{/if}}
</td>
<td class="call-date"><span>${datetime}</span></td>
<td class="call-agent">
${answeredBy.displayName}
</td>
<td class="call-client">${contactTitle}</td>
<td class="call-duration">${durationString}</td>
{{if ASC.CRM.Data.IsCRMAdmin}}
<td class="call-cost">${cost}</td>
{{/if}}
</tr>
</script>
<script id="voip-call-view-tmpl" type="text/x-jquery-tmpl">
<div class="header-with-menu">
<a href="settings.aspx?type=voip.calls" class="header-back-link"></a>
<span>${ASC.CRM.Resources.CRMVoipResource.Call} ${'#' + id}</span>
</div>
<div id="call-info-box">
<div class="call-info-row">
<span class="call-info-title">${ASC.CRM.Resources.CRMVoipResource.CallType}:</span>
<span class="call-info-value">${typeString}</span>
</div>
<div class="call-info-row">
<span class="call-info-title">${ASC.CRM.Resources.CRMVoipResource.CallDatetime}:</span>
<span class="call-info-value">${datetime}</span>
</div>
<div class="call-info-row">
<span class="call-info-title">${ASC.CRM.Resources.CRMVoipResource.CallClient}:</span>
<span class="call-info-value">${contact.displayName}</span>
</div>
<div class="call-info-row">
<span class="call-info-title">${ASC.CRM.Resources.CRMVoipResource.CallDuration}:</span>
<span class="call-info-value">${durationString}</span>
</div>
{{if ASC.CRM.Data.IsCRMAdmin}}
<div class="call-info-row">
<span class="call-info-title">${ASC.CRM.Resources.CRMVoipResource.CallCost}:</span>
<span class="call-info-value">${cost}$</span>
</div>
{{/if}}
</div>
<table id="call-redirections-list" class="table-list height32">
<thead>
<tr>
<th class="call-redirection-agent">${ASC.CRM.Resources.CRMVoipResource.CallAgent}</th>
<th class="call-redirection-waiting-time">${ASC.CRM.Resources.CRMVoipResource.CallWaitingTime}</th>
<th class="call-redirection-duration">${ASC.CRM.Resources.CRMVoipResource.CallDuration}</th>
</tr>
</thead>
</table>
</script>
<script id="voip-header-tmpl" type="text/x-jquery-tmpl">
{{if $data > 0}}
<div>
${ASC.CRM.Resources.CRMVoipResource.NumbersCountMsg}: <strong>${$data}</strong>.
{{html jq.format(ASC.CRM.Resources.CRMVoipResource.NumbersCountDscrMsg, '<a href="settings.aspx?type=voip.numbers" class="link underline blue" target="_blank">', '</a>')}}
</div>
{{else}}
<div>
{{html jq.format(ASC.CRM.Resources.CRMVoipResource.NoNumbersMsg, '<a href="settings.aspx?type=voip.numbers" class="link underline blue" target="_blank">', '</a>')}}
</div>
{{/if}}
</script>
<script id="voip-common-settings-tmpl" type="text/x-jquery-tmpl">
<div class="common-setting-item">
<div class="header-base-small">${ASC.CRM.Resources.CRMVoipResource.IncomingCallsQueueSize}</div>
<select id="queue-size-selector" class="comboBox">
<option value="5" {{if queue.size == 5}} selected="selected" {{/if}}>5</option>
<option value="10" {{if queue.size == 10}} selected="selected" {{/if}}>10</option>
<option value="15" {{if queue.size == 15}} selected="selected" {{/if}}>15</option>
</select>
</div>
<div class="common-setting-item">
<div class="header-base-small">${ASC.CRM.Resources.CRMVoipResource.WaitingTimeout}</div>
<select id="queue-wait-time-selector" class="comboBox">
<option value="5" {{if queue.waitTime == 300}} selected="selected" {{/if}}>${ASC.CRM.Resources.CRMVoipResource.WaitingTimeout5Minutes}</option>
<option value="10" {{if queue.waitTime == 600}} selected="selected" {{/if}}>${ASC.CRM.Resources.CRMVoipResource.WaitingTimeout10Minutes}</option>
<option value="15" {{if queue.waitTime == 900}} selected="selected" {{/if}}>${ASC.CRM.Resources.CRMVoipResource.WaitingTimeout15Minutes}</option>
</select>
</div>
<div class="common-setting-item">
<div class="header-base-small">${ASC.CRM.Resources.CRMVoipResource.OperatorPause}</div>
<select id="operator-pause-selector" class="comboBox">
<option value="0" {{if !pause}} selected="selected" {{/if}}>${ASC.CRM.Resources.CRMVoipResource.OperatorPauseDisabled}</option>
<option value="1" {{if pause}} selected="selected" {{/if}}>${ASC.CRM.Resources.CRMVoipResource.OperatorPauseEnabled}</option>
</select>
</div>
</script>
<script id="voip-ringtones-tmpl" type="text/x-jquery-tmpl">
<div id="ringtone-group-${audioType}" class="ringtone-group" data-audiotype="${audioType}">
<div class="ringtone-group-box with-entity-menu clearFix">
<div class="cell switcher">
<div class="expander-icon {{if ringtones.length == 0}} display-none {{/if}}"></div>
</div>
<div class="cell title">
${name}
</div>
<div class="cell actions entity-menu">
<div class="studio-action-panel">
<ul class="dropdown-content">
<li id="add-ringtone-${audioType}-btn" class="dropdown-item">${ASC.CRM.Resources.CRMVoipResource.AddRingtoneBtn}</li>
</ul>
</div>
</div>
</div>
<div class="ringtones-box">
{{tmpl(ringtones) "voip-ringtone-tmpl"}}
</div>
</div>
</script>
<script id="voip-ringtone-tmpl" type="text/x-jquery-tmpl">
<div class="ringtone with-entity-menu clearFix" data-filename="${name}">
<div class="cell title">
<div class="loader16"></div>
<button class="button gray btn-icon ringtone-play-btn __play" data-path="${path}"></button>
${name}
</div>
{{if !isDefault }}
<div class="cell actions entity-menu">
<div class="studio-action-panel">
<ul class="dropdown-content">
<li class="dropdown-item delete-ringtone-btn">${ASC.CRM.Resources.CRMVoipResource.DeleteRingtoneBtn}</li>
</ul>
</div>
</div>
{{/if}}
</div>
</script>
<script id="voip-number-selector-option-tmpl" type="text/x-jquery-tmpl">
<option value="${id}">${number}</option>
</script>
<script id="voip-settings-tmpl" type="text/x-jquery-tmpl">
<div id="alias-setting-box" class="clearFix">
<div class="settings-block">
<div class="header-base">${ASC.CRM.Resources.CRMVoipResource.Alias}</div>
<input type="text" value="${alias}" id="number-alias-input" class="textEdit" placeholder="${ASC.CRM.Resources.CRMVoipResource.AliasPlaceholder}" maxlength="30"/>
</div>
<div class="settings-help-block">
<p>{{html jq.format(ASC.CRM.Resources.CRMVoipResource.AliasDscrMsg, "<strong>", "</strong>")}}</p>
</div>
</div>
<div class="clearFix">
<div id="quick-setting" class="settings-block">
<div class="header-base">${ASC.CRM.Resources.CRMVoipResource.QuickTuning}</div>
<div class="quick-setting-item">
<a id="outgoing-calls-setting-btn" class="on_off_button ${settings.allowOutgoingCalls ? ' on' : 'off' }"></a>
${ASC.CRM.Resources.CRMVoipResource.OutgoingCalls}
</div>
<div class="quick-setting-item">
<a id="record-incoming-setting-btn" class="on_off_button ${settings.record ? ' on' : 'off' }"></a>
${ASC.CRM.Resources.CRMVoipResource.RecordingCalls}
</div>
<div class="quick-setting-item">
<a id="working-hours-setting-btn" class="on_off_button ${settings.workingHours && settings.workingHours.enabled ? ' on' : 'off' }"></a>
${ASC.CRM.Resources.CRMVoipResource.WorkingHours}
<div class="working-hours-inputs-box">
<div>
<input type="text" class="textEdit" ${settings.workingHours && settings.workingHours.enabled ? "" : "disabled" } id="working-hours-from-input" value="${settings.workingHours && settings.workingHours.from ? settings.workingHours.from.slice(0, 5) : " "}" /> -
<input type="text" class="textEdit" ${settings.workingHours && settings.workingHours.enabled ? "" : "disabled" } id="working-hours-to-input" value="${settings.workingHours && settings.workingHours.to ? settings.workingHours.to.slice(0, 5) : " "}" />
</div>
<span id="working-hours-invalid-format-error" class="working-hours-error">${ASC.CRM.Resources.CRMVoipResource.WorkingHoursFormatTip}</span>
<span id="working-hours-invalid-interval-error" class="working-hours-error">${ASC.CRM.Resources.CRMVoipResource.WorkingHoursFormatErrorMsg}</span>
</div>
</div>
</div>
<div class="settings-help-block">
<p>{{html jq.format(ASC.CRM.Resources.CRMVoipResource.QuickTuningDscrMsg, "<strong>", "</strong>")}}</p>
</div>
</div>
<div id="ringtones-setting-box" class="clearFix">
<div class="settings-block">
<div class="header-base">${ASC.CRM.Resources.CRMVoipResource.RingtonesTuning}</div>
<div class="ringtone-setting-item">
<div class="header-base-small">
${ASC.CRM.Resources.CRMVoipResource.GreetingRingtones}
</div>
<select id="greeting-ringtone-selector" class="comboBox ringtone-selector">
<option value="" {{if settings.greetingAudio === ""}} selected="selected" {{/if}}>${ASC.CRM.Resources.CRMVoipResource.UnspecifiedOption}</option>
{{each settings.ringtones.greeting}}
<option value="${path}" {{if settings.greetingAudio === path}} selected="selected" {{/if}}>${name}</option>
{{/each}}
</select>
<button class="button gray btn-icon ringtone-play-btn __play {{if !settings.greetingAudio}} disable {{/if}}" id="greeting-ringtone-play-btn" data-src="${settings.greetingAudio}" data-type="greeting"></button>
<button class="button gray btn-icon __upload" id="greeting-ringtone-load-btn" onclick=" return false; "></button>
</div>
<div class="ringtone-setting-item">
<div class="header-base-small">
${ASC.CRM.Resources.CRMVoipResource.QueueRingtones}
</div>
<select id="queue-wait-ringtone-selector" class="comboBox ringtone-selector">
<option value="" {{if settings.queue === ""}} selected="selected" {{/if}}>${ASC.CRM.Resources.CRMVoipResource.UnspecifiedOption}</option>
{{each settings.ringtones.queue}}
<option value="${path}" {{if settings.queue.waitUrl === path}} selected="selected" {{/if}}>${name}</option>
{{/each}}
</select>
<button class="button gray btn-icon ringtone-play-btn __play {{if !settings.queue || !settings.queue.waitUrl}} disable {{/if}}" id="queue-wait-ringtone-play-btn" data-src="${settings.queue.waitUrl}" data-type="queue"></button>
<button class="button gray btn-icon __upload" id="queue-wait-ringtone-load-btn" onclick=" return false; "></button>
</div>
<div class="ringtone-setting-item">
<div class="header-base-small">
${ASC.CRM.Resources.CRMVoipResource.VoicemailRingtones}
</div>
<select id="voicemail-ringtone-selector" class="comboBox ringtone-selector">
<option value="" {{if settings.voiceMail === ""}} selected="selected" {{/if}}>${ASC.CRM.Resources.CRMVoipResource.UnspecifiedOption}</option>
{{each settings.ringtones.voicemail}}
<option value="${path}" {{if settings.voiceMail === path}} selected="selected" {{/if}}>${name}</option>
{{/each}}
</select>
<button class="button gray btn-icon ringtone-play-btn __play {{if !settings.voiceMail}} disable {{/if}}" id="voicemail-ringtone-play-btn" data-src="${settings.voiceMail}" data-type="voice"></button>
<button class="button gray btn-icon __upload" id="voicemail-ringtone-load-btn" onclick=" return false; "></button>
</div>
</div>
<div class="settings-help-block">
<p>{{html jq.format(ASC.CRM.Resources.CRMVoipResource.RingtonesTuningDscrMsg, "<strong>", "</strong>")}}</p>
</div>
</div>
</script>
<script id="voip-operator-tmpl" type="text/x-jquery-tmpl">
{{each settings.operators}}
<div class="operator with-entity-menu" data-operatorid="${id}">
<div class="cell code"></div>
<div class="cell title">
<img src="${userInfo.avatarSmall}" alt="${userInfo.displayName}" />
${userInfo.displayName}
</div>
<div class="cell outgoing-calls">
<a class="on_off_button ${allowOutgoingCalls ? " on" : "off" } ${$data.settings.allowOutgoingCalls ? "" : "disable" }"></a>
</div>
<div class="cell incoming-recording">
<a class="on_off_button ${record ? " on" : "off" } ${$data.settings.record ? "" : "disable" }"></a>
</div>
<div class="cell actions entity-menu">
<div class="studio-action-panel">
<ul class="dropdown-content">
<li class="dropdown-item delete-operator-btn">${ASC.CRM.Resources.CRMVoipResource.DeleteBtn}</li>
</ul>
</div>
</div>
</div>
{{/each}}
</script>
<script id="voip-ringtone-selector-option-tmpl" type="text/x-jquery-tmpl">
<option value="${path}">${name}</option>
</script>
<script id="voip-existing-number-tmpl" type="text/x-jquery-tmpl">
<div id="enumber${id}" class="number" data-numberid="${id}">
<div class="number-box with-entity-menu clearFix">
<div class="cell switcher">
<div class="expander-icon"></div>
</div>
<div class="cell title">
${number}<span class="support-level">${alias}</span>
</div>
<div class="cell outgoing-calls">
<a class="on_off_button ${settings.allowOutgoingCalls ? " on" : "off" }" data-operator-btn-selector=".outgoing-calls"></a>
</div>
<div class="cell recording-calls">
<a class="on_off_button ${settings.record ? " on" : "off" }" data-operator-btn-selector=".recording-calls"></a>
</div>
<div class="cell actions entity-menu">
<div class="studio-action-panel">
<ul class="dropdown-content">
<li class="dropdown-item edit-number-btn">${ASC.CRM.Resources.CRMVoipResource.EditBtn}</li>
<li class="dropdown-item show-remove-number-btn">${ASC.CRM.Resources.CRMVoipResource.DeleteBtn}</li>
</ul>
</div>
</div>
</div>
<div class="operators-box">
<div class="add-operators-box">
<span class="add-operators-btn link dotline plus">${ASC.CRM.Resources.CRMVoipResource.AddOperatorsBtn}</span>
</div>
{{tmpl "voip-operators-tmpl"}}
</div>
</div>
</script>
<script id="voip-operators-tmpl" type="text/x-jquery-tmpl">
{{each settings.operators}}
<div class="operator with-entity-menu" data-operatorid="${id}">
<div class="cell code"></div>
<div class="cell title">
<img src="${userInfo.avatarSmall}" alt="${userInfo.displayName}" />
${userInfo.displayName}
</div>
<div class="cell outgoing-calls">
<a class="on_off_button ${allowOutgoingCalls ? " on" : "off" } ${$data.settings.allowOutgoingCalls ? "" : "disable" }"></a>
</div>
<!--<div class="cell voicemail"></div>-->
<div class="cell recording-calls">
<a class="on_off_button ${record ? " on" : "off" } ${$data.settings.record ? "" : "disable" }"></a>
</div>
<div class="cell actions entity-menu">
<div class="studio-action-panel">
<ul class="dropdown-content">
<li class="dropdown-item delete-operator-btn">${ASC.CRM.Resources.CRMVoipResource.DeleteBtn}</li>
</ul>
</div>
</div>
</div>
{{/each}}
</script>
<script id="voip-countries-list-tmpl" type="text/x-jquery-tmpl">
<div class="studio-action-panel">
<ul class="dropdown-content">
{{each countries}}
<li class="dropdown-item">
<span class="voip-flag ${iso}" data-iso="${iso}" data-code="${code}"></span>${title}
</li>
{{/each}}
</ul>
</div>
</script>
<script id="voip-available-number-tmpl" type="text/x-jquery-tmpl">
<div id="anumber${number}" class="number">
<input type="radio" name="buy-number-radio" data-number="${number}" {{if id}} data-numberId="${id}" {{/if}}/>
<div class="number-value">${number}</div>
</div>
</script>

View File

@ -1,3 +1,29 @@
// (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
/*
*
* (c) Copyright Ascensio System Limited 2010-2018
@ -51,14 +77,14 @@ namespace ASC.Web.CRM.Classes
[Scope]
public class PdfCreator
{
private InvoiceFormattedData _invoiceFormattedData;
private DaoFactory _daoFactory;
private IServiceProvider _serviceProvider;
private DocumentServiceConnector _documentServiceConnector;
private OrganisationLogoManager _organisationLogoManager;
private Files.Classes.PathProvider _filesPathProvider;
private ILogger _logger;
private IHttpClientFactory _clientFactory;
private readonly InvoiceFormattedData _invoiceFormattedData;
private readonly DaoFactory _daoFactory;
private readonly IServiceProvider _serviceProvider;
private readonly DocumentServiceConnector _documentServiceConnector;
private readonly OrganisationLogoManager _organisationLogoManager;
private readonly Files.Classes.PathProvider _filesPathProvider;
private readonly ILogger _logger;
private readonly IHttpClientFactory _clientFactory;
public PdfCreator(ILogger logger,
@ -191,7 +217,7 @@ namespace ASC.Web.CRM.Classes
var revisionId = DocumentServiceConnector.GenerateRevisionId(Guid.NewGuid().ToString());
var (_, urlToFile) = await _documentServiceConnector.GetConvertedUriAsync(externalUri, FormatDocx, FormatPdf, revisionId, null, null, null, false);
var (_, urlToFile) = await _documentServiceConnector.GetConvertedUriAsync(externalUri, FormatDocx, FormatPdf, revisionId, null, null, null, null, false);
_logger.LogDebug("PdfCreator. GetUrlToFile. urlToFile = {0}", urlToFile);
@ -210,7 +236,7 @@ namespace ASC.Web.CRM.Classes
var revisionId = DocumentServiceConnector.GenerateRevisionId(Guid.NewGuid().ToString());
await _documentServiceConnector.GetConvertedUriAsync(externalUri, FormatDocx, FormatPdf, revisionId, null, null, null, true);
await _documentServiceConnector.GetConvertedUriAsync(externalUri, FormatDocx, FormatPdf, revisionId, null, null, null, null, true);
return new ConverterData
{
@ -233,7 +259,7 @@ namespace ASC.Web.CRM.Classes
private async Task<File<int>> internalGetConvertedFileAsync(ConverterData data, DaoFactory daoFactory)
{
var (_, urlToFile) = await _documentServiceConnector.GetConvertedUriAsync(data.StorageUrl, FormatDocx, FormatPdf, data.RevisionId, null, null, null, true);
var (_, urlToFile) = await _documentServiceConnector.GetConvertedUriAsync(data.StorageUrl, FormatDocx, FormatPdf, data.RevisionId, null, null, null, null, true);
if (string.IsNullOrEmpty(urlToFile))
{

View File

@ -1,3 +1,29 @@
// (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
/*
*
* (c) Copyright Ascensio System Limited 2010-2018
@ -48,18 +74,18 @@ namespace ASC.Web.CRM.Classes
[Scope]
public class ReportHelper
{
private CurrencyProvider _currencyProvider;
private IHttpContextAccessor _httpContext;
private SecurityContext _securityContext;
private DocbuilderReportsUtilityHelper _docbuilderReportsUtilityHelper;
private DaoFactory _daoFactory;
private IServiceProvider _serviceProvider;
private IServiceScopeFactory _serviceScopeFactory;
private Global _global;
private SettingsManager _settingsManager;
private TenantUtil _tenantUtil;
private TenantManager _tenantManager;
private IHttpClientFactory _clientFactory;
private readonly CurrencyProvider _currencyProvider;
private readonly IHttpContextAccessor _httpContext;
private readonly SecurityContext _securityContext;
private readonly DocbuilderReportsUtilityHelper _docbuilderReportsUtilityHelper;
private readonly DaoFactory _daoFactory;
private readonly IServiceProvider _serviceProvider;
private readonly IServiceScopeFactory _serviceScopeFactory;
private readonly Global _global;
private readonly SettingsManager _settingsManager;
private readonly TenantUtil _tenantUtil;
private readonly TenantManager _tenantManager;
private readonly IHttpClientFactory _clientFactory;
public ReportHelper(TenantManager tenantManager,
TenantUtil tenantUtil,
@ -116,9 +142,6 @@ namespace ASC.Web.CRM.Classes
case ReportType.WorkloadByInvoices:
reportName = CRMReportResource.WorkloadByInvoicesReport;
break;
case ReportType.WorkloadByVoip:
reportName = CRMReportResource.WorkloadByVoipReport;
break;
case ReportType.SummaryForThePeriod:
reportName = CRMReportResource.SummaryForThePeriodReport;
break;
@ -155,8 +178,6 @@ namespace ASC.Web.CRM.Classes
// return reportDao.CheckWorkloadByDealsReportData(timePeriod, managers);
// case ReportType.WorkloadByInvoices:
// return reportDao.CheckWorkloadByInvoicesReportData(timePeriod, managers);
// case ReportType.WorkloadByVoip:
// return reportDao.CheckWorkloadByViopReportData(timePeriod, managers);
// case ReportType.SummaryForThePeriod:
// return reportDao.CheckSummaryForThePeriodReportData(timePeriod, managers);
// case ReportType.SummaryAtThisMoment:
@ -171,7 +192,7 @@ namespace ASC.Web.CRM.Classes
var reportDao = _daoFactory.GetReportDao();
if (reportType == ReportType.WorkloadByTasks || reportType == ReportType.WorkloadByInvoices ||
reportType == ReportType.WorkloadByContacts || reportType == ReportType.WorkloadByVoip) return null;
reportType == ReportType.WorkloadByContacts) return null;
var crmSettings = _settingsManager.Load<CrmSettings>();
var defaultCurrency = _currencyProvider.Get(crmSettings.DefaultCurrency);
@ -202,8 +223,6 @@ namespace ASC.Web.CRM.Classes
return reportDao.GetWorkloadByDealsReportData(timePeriod, managers, defaultCurrency);
case ReportType.WorkloadByInvoices:
return reportDao.GetWorkloadByInvoicesReportData(timePeriod, managers);
case ReportType.WorkloadByVoip:
return reportDao.GetWorkloadByViopReportData(timePeriod, managers);
case ReportType.SummaryForThePeriod:
return reportDao.GetSummaryForThePeriodReportData(timePeriod, managers, defaultCurrency);
case ReportType.SummaryAtThisMoment:

View File

@ -598,10 +598,6 @@ public class SettingsController : BaseSettingsController
{
try
{
if (validateKeyProvider is TwilioProvider twilioLoginProvider)
{
twilioLoginProvider.ClearOldNumbers();
}
if (validateKeyProvider is BitlyLoginProvider bitly)
{
_urlShortener.Instance = null;

View File

@ -30,7 +30,6 @@
<ProjectReference Include="..\..\common\ASC.IPSecurity\ASC.IPSecurity.csproj" />
<ProjectReference Include="..\..\common\ASC.MessagingSystem\ASC.MessagingSystem.csproj" />
<ProjectReference Include="..\..\common\ASC.Notify.Textile\ASC.Notify.Textile.csproj" />
<ProjectReference Include="..\..\common\ASC.VoipService\ASC.VoipService.csproj" />
</ItemGroup>
<ItemGroup>
<Compile Update="PublicResources\WebPatternResource.Designer.cs">
@ -427,5 +426,6 @@
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="SixLabors.ImageSharp.Drawing" Version="1.0.0-beta14" />
<PackageReference Include="Twilio" Version="5.6.0" />
</ItemGroup>
</Project>

View File

@ -87,7 +87,6 @@ global using ASC.Notify.Patterns;
global using ASC.Notify.Recipients;
global using ASC.Notify.Textile;
global using ASC.Security.Cryptography;
global using ASC.VoipService.Dao;
global using ASC.Web.Core;
global using ASC.Web.Core.Helpers;
global using ASC.Web.Core.HttpHandlers;

View File

@ -34,8 +34,6 @@ public static class Actions
public static readonly INotifyAction SelfProfileUpdated = new NotifyAction("self_profile_updated", "self profile updated");
public static readonly INotifyAction UserHasJoin = new NotifyAction("user_has_join", "user has join");
public static readonly INotifyAction UserMessageToAdmin = new NotifyAction("for_admin_notify", "for_admin_notify");
public static readonly INotifyAction VoipWarning = new NotifyAction("admin_voip_warning", "admin_voip_warning");
public static readonly INotifyAction VoipBlocked = new NotifyAction("admin_voip_blocked", "admin_voip_blocked");
public static readonly INotifyAction RequestTariff = new NotifyAction("request_tariff", "request_tariff");
public static readonly INotifyAction RequestLicense = new NotifyAction("request_license", "request_license");

View File

@ -149,20 +149,6 @@ public class StudioNotifyService
new TagValue(Tags.Body, message));
}
#region Voip
public void SendToAdminVoipWarning(double balance)
{
_client.SendNoticeAsync(Actions.VoipWarning, null, new TagValue(Tags.Body, balance));
}
public void SendToAdminVoipBlocked()
{
_client.SendNoticeAsync(Actions.VoipBlocked, null);
}
#endregion
#region User Password
public void UserPasswordChange(UserInfo userInfo)

View File

@ -68,9 +68,6 @@ public class StudioNotifySource : NotifySource
Actions.UserMessageToAdmin,
Actions.VoipWarning,
Actions.VoipBlocked,
Actions.SaasAdminActivationV115,
Actions.EnterpriseAdminActivationV10,
Actions.EnterpriseWhitelabelAdminActivationV10,
@ -249,9 +246,7 @@ public class StudioNotifySource : NotifySource
{
if (Actions.SelfProfileUpdated.ID == action.ID ||
Actions.UserHasJoin.ID == action.ID ||
Actions.UserMessageToAdmin.ID == action.ID ||
Actions.VoipWarning.ID == action.ID ||
Actions.VoipBlocked.ID == action.ID
Actions.UserMessageToAdmin.ID == action.ID
)
{
return Actions.AdminNotify;

View File

@ -94,7 +94,6 @@ public class SetupInfo
public string ShareFacebookUrl { get; private set; }
public string ControlPanelUrl { get; private set; }
public string FontOpenSansUrl { get; private set; }
public bool VoipEnabled { get; private set; }
public string StartProductList { get; private set; }
public string SsoSamlLoginUrl { get; private set; }
public string DownloadForDesktopUrl { get; private set; }
@ -179,7 +178,6 @@ public class SetupInfo
ShareFacebookUrl = GetAppSettings("web.share.facebook", "");
ControlPanelUrl = GetAppSettings("web:controlpanel:url", "");
FontOpenSansUrl = GetAppSettings("web.font.opensans.url", "");
VoipEnabled = GetAppSettings("voip.enabled", true);
StartProductList = GetAppSettings("web.start.product.list", "");
SsoSamlLoginUrl = GetAppSettings("web.sso.saml.login.url", "");
SsoSamlLogoutUrl = GetAppSettings("web.sso.saml.logout.url", "");

View File

@ -26,7 +26,7 @@
namespace ASC.Web.Core.Sms;
[Scope(Additional = typeof(TwilioProviderExtention))]
[Scope]
public class SmsProviderManager
{
private readonly ConsumerFactory _consumerFactory;
@ -392,12 +392,6 @@ public class TwilioProvider : SmsProvider, IValidateKeysProvider
get { return this["twiliosender"]; }
}
private readonly AuthContext _authContext;
private readonly TenantUtil _tenantUtil;
private readonly SecurityContext _securityContext;
private readonly BaseCommonLinkUtility _baseCommonLinkUtility;
private readonly TwilioProviderCleaner _twilioProviderCleaner;
public override bool Enable()
{
return
@ -434,41 +428,12 @@ public class TwilioProvider : SmsProvider, IValidateKeysProvider
return Task.FromResult(false);
}
public TwilioProvider()
{
}
public TwilioProvider(
AuthContext authContext,
TenantUtil tenantUtil,
SecurityContext securityContext,
BaseCommonLinkUtility baseCommonLinkUtility,
TwilioProviderCleaner twilioProviderCleaner,
TenantManager tenantManager,
CoreBaseSettings coreBaseSettings,
CoreSettings coreSettings,
IConfiguration configuration,
ICacheNotify<ConsumerCacheItem> cache,
ConsumerFactory consumerFactory,
ILogger<TwilioProvider> options,
IHttpClientFactory clientFactory,
ICache memCache,
string name, int order, Dictionary<string, string> props)
: base(tenantManager, coreBaseSettings, coreSettings, configuration, cache, consumerFactory, options, clientFactory, memCache, name, order, props)
{
_authContext = authContext;
_tenantUtil = tenantUtil;
_securityContext = securityContext;
_baseCommonLinkUtility = baseCommonLinkUtility;
_twilioProviderCleaner = twilioProviderCleaner;
}
public bool ValidateKeys()
{
try
{
new VoipService.Twilio.TwilioProvider(AccountSid, AuthToken, _authContext, _tenantUtil, _securityContext, _baseCommonLinkUtility).GetExistingPhoneNumbers();
IncomingPhoneNumberResource.Read(client: new TwilioRestClient(AccountSid, AuthToken));
return true;
}
catch (Exception)
@ -476,81 +441,9 @@ public class TwilioProvider : SmsProvider, IValidateKeysProvider
return false;
}
}
public void ClearOldNumbers()
{
_twilioProviderCleaner.ClearOldNumbers(AccountSid, AuthToken);
}
}
[Scope]
public class TwilioSaaSProvider : TwilioProvider
{
public TwilioSaaSProvider()
{
}
public TwilioSaaSProvider(
AuthContext authContext,
TenantUtil tenantUtil,
SecurityContext securityContext,
BaseCommonLinkUtility baseCommonLinkUtility,
TwilioProviderCleaner twilioProviderCleaner,
TenantManager tenantManager,
CoreBaseSettings coreBaseSettings,
CoreSettings coreSettings,
IConfiguration configuration,
ICacheNotify<ConsumerCacheItem> cache,
ConsumerFactory consumerFactory,
ILogger<TwilioSaaSProvider> options,
IHttpClientFactory clientFactory,
ICache memCache,
string name, int order)
: base(authContext, tenantUtil, securityContext, baseCommonLinkUtility, twilioProviderCleaner, tenantManager, coreBaseSettings, coreSettings, configuration, cache, consumerFactory, options, clientFactory, memCache, name, order, null)
{
}
}
[Scope]
public class TwilioProviderCleaner
{
private readonly VoipDao _voipDao;
private readonly AuthContext _authContext;
private readonly TenantUtil _tenantUtil;
private readonly SecurityContext _securityContext;
private readonly BaseCommonLinkUtility _baseCommonLinkUtility;
public TwilioProviderCleaner(VoipDao voipDao, AuthContext authContext, TenantUtil tenantUtil, SecurityContext securityContext, BaseCommonLinkUtility baseCommonLinkUtility)
{
_voipDao = voipDao;
_authContext = authContext;
_tenantUtil = tenantUtil;
_securityContext = securityContext;
_baseCommonLinkUtility = baseCommonLinkUtility;
}
public void ClearOldNumbers(string key, string secret)
{
if (string.IsNullOrEmpty(key) || string.IsNullOrEmpty(secret))
{
return;
}
var provider = new VoipService.Twilio.TwilioProvider(key, secret, _authContext, _tenantUtil, _securityContext, _baseCommonLinkUtility);
var numbers = _voipDao.GetNumbers();
foreach (var number in numbers)
{
provider.DisablePhone(number);
_voipDao.DeleteNumber(number.Id);
}
}
}
public static class TwilioProviderExtention
{
public static void Register(DIHelper services)
{
services.TryAdd<TwilioSaaSProvider>();
}
}

View File

@ -100,11 +100,6 @@ public class WebItemManager
get { return new Guid("{BF88953E-3C43-4850-A3FB-B1E43AD53A3E}"); }
}
public static Guid VoipModuleID
{
get { return new Guid("{46CFA73A-F320-46CF-8D5B-CD82E1D67F26}"); }
}
private readonly IServiceProvider _serviceProvider;
private readonly IConfiguration _configuration;