EF: Voip
This commit is contained in:
parent
6cd6eedde0
commit
a47196dc05
@ -28,7 +28,7 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Linq.Expressions;
|
||||
using System.Reflection;
|
||||
|
||||
using ASC.Core.Common.EF;
|
||||
using ASC.Core.Tenants;
|
||||
using ASC.Core.Users;
|
||||
@ -634,34 +634,4 @@ namespace ASC.Core.Data
|
||||
return result.Distinct().ToList();
|
||||
}
|
||||
}
|
||||
|
||||
public static class LinqExtensions
|
||||
{
|
||||
public static IQueryable<T> OrderBy<T>(this IQueryable<T> query, string name, bool sortOrderAsc)
|
||||
{
|
||||
var propInfo = GetPropertyInfo(typeof(T), name);
|
||||
var expr = GetOrderExpression(typeof(T), propInfo);
|
||||
|
||||
var method = typeof(Queryable).GetMethods().FirstOrDefault(m => m.Name == (sortOrderAsc ? "OrderBy" : "OrderByDescending") && m.GetParameters().Length == 2);
|
||||
var genericMethod = method.MakeGenericMethod(typeof(T), propInfo.PropertyType);
|
||||
return (IQueryable<T>)genericMethod.Invoke(null, new object[] { query, expr });
|
||||
}
|
||||
|
||||
private static PropertyInfo GetPropertyInfo(Type objType, string name)
|
||||
{
|
||||
var properties = objType.GetProperties();
|
||||
var matchedProperty = properties.FirstOrDefault(p => p.Name.ToLower() == name.ToLower());
|
||||
if (matchedProperty == null)
|
||||
throw new ArgumentException("name");
|
||||
|
||||
return matchedProperty;
|
||||
}
|
||||
private static LambdaExpression GetOrderExpression(Type objType, PropertyInfo pi)
|
||||
{
|
||||
var paramExpr = Expression.Parameter(objType);
|
||||
var propAccess = Expression.PropertyOrField(paramExpr, pi.Name);
|
||||
var expr = Expression.Lambda(propAccess, paramExpr);
|
||||
return expr;
|
||||
}
|
||||
}
|
||||
}
|
22
common/ASC.Core.Common/EF/Context/VoipDbContext.cs
Normal file
22
common/ASC.Core.Common/EF/Context/VoipDbContext.cs
Normal file
@ -0,0 +1,22 @@
|
||||
using ASC.Core.Common.EF.Model;
|
||||
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
namespace ASC.Core.Common.EF.Context
|
||||
{
|
||||
public class VoipDbContext : BaseDbContext
|
||||
{
|
||||
public DbSet<VoipNumber> VoipNumbers { get; set; }
|
||||
public DbSet<DbVoipCall> VoipCalls { get; set; }
|
||||
public DbSet<CrmContact> CrmContact { get; set; }
|
||||
}
|
||||
|
||||
public static class VoipDbExtension
|
||||
{
|
||||
public static IServiceCollection AddVoipDbContextService(this IServiceCollection services)
|
||||
{
|
||||
return services.AddDbContextManagerService<VoipDbContext>();
|
||||
}
|
||||
}
|
||||
}
|
37
common/ASC.Core.Common/EF/LinqExtensions.cs
Normal file
37
common/ASC.Core.Common/EF/LinqExtensions.cs
Normal file
@ -0,0 +1,37 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Linq.Expressions;
|
||||
using System.Reflection;
|
||||
|
||||
namespace ASC.Core.Common.EF
|
||||
{
|
||||
public static class LinqExtensions
|
||||
{
|
||||
public static IQueryable<T> OrderBy<T>(this IQueryable<T> query, string name, bool sortOrderAsc)
|
||||
{
|
||||
var propInfo = GetPropertyInfo(typeof(T), name);
|
||||
var expr = GetOrderExpression(typeof(T), propInfo);
|
||||
|
||||
var method = typeof(Queryable).GetMethods().FirstOrDefault(m => m.Name == (sortOrderAsc ? "OrderBy" : "OrderByDescending") && m.GetParameters().Length == 2);
|
||||
var genericMethod = method.MakeGenericMethod(typeof(T), propInfo.PropertyType);
|
||||
return (IQueryable<T>)genericMethod.Invoke(null, new object[] { query, expr });
|
||||
}
|
||||
|
||||
private static PropertyInfo GetPropertyInfo(Type objType, string name)
|
||||
{
|
||||
var properties = objType.GetProperties();
|
||||
var matchedProperty = properties.FirstOrDefault(p => p.Name.ToLower() == name.ToLower());
|
||||
if (matchedProperty == null)
|
||||
throw new ArgumentException("name");
|
||||
|
||||
return matchedProperty;
|
||||
}
|
||||
private static LambdaExpression GetOrderExpression(Type objType, PropertyInfo pi)
|
||||
{
|
||||
var paramExpr = Expression.Parameter(objType);
|
||||
var propAccess = Expression.PropertyOrField(paramExpr, pi.Name);
|
||||
var expr = Expression.Lambda(propAccess, paramExpr);
|
||||
return expr;
|
||||
}
|
||||
}
|
||||
}
|
57
common/ASC.Core.Common/EF/Model/CrmContact.cs
Normal file
57
common/ASC.Core.Common/EF/Model/CrmContact.cs
Normal file
@ -0,0 +1,57 @@
|
||||
using System;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
|
||||
namespace ASC.Core.Common.EF.Model
|
||||
{
|
||||
[Table("crm_contact")]
|
||||
public class CrmContact
|
||||
{
|
||||
public int Id { get; set; }
|
||||
|
||||
[Column("tenant_id")]
|
||||
public int TenantId { get; set; }
|
||||
|
||||
[Column("is_company")]
|
||||
public bool IsCompany { get; set; }
|
||||
public string Notes { get; set; }
|
||||
public string Title { get; set; }
|
||||
|
||||
[Column("first_name")]
|
||||
public string FirstName { get; set; }
|
||||
|
||||
[Column("last_name")]
|
||||
public string LastName { get; set; }
|
||||
|
||||
[Column("company_name")]
|
||||
public string CompanyName { get; set; }
|
||||
public string Industry { get; set; }
|
||||
|
||||
[Column("status_id")]
|
||||
public int StatusId { get; set; }
|
||||
|
||||
[Column("company_id")]
|
||||
public int CompanyId { get; set; }
|
||||
|
||||
[Column("contact_type_id")]
|
||||
public int ContactTypeId { get; set; }
|
||||
|
||||
[Column("create_by")]
|
||||
public Guid CreateBy { get; set; }
|
||||
|
||||
[Column("create_on")]
|
||||
public DateTime CreateOn { get; set; }
|
||||
|
||||
[Column("last_modifed_by")]
|
||||
public Guid LastModifedBy { get; set; }
|
||||
|
||||
[Column("last_modifed_on")]
|
||||
public DateTime LastModifedOn { get; set; }
|
||||
|
||||
[Column("display_name")]
|
||||
public string DisplayName { get; set; }
|
||||
|
||||
[Column("is_shared")]
|
||||
public bool IsShared { get; set; }
|
||||
public string Currency { get; set; }
|
||||
}
|
||||
}
|
52
common/ASC.Core.Common/EF/Model/DbVoipCall.cs
Normal file
52
common/ASC.Core.Common/EF/Model/DbVoipCall.cs
Normal file
@ -0,0 +1,52 @@
|
||||
using System;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
|
||||
namespace ASC.Core.Common.EF.Model
|
||||
{
|
||||
[Table("crm_voip_calls")]
|
||||
public class DbVoipCall
|
||||
{
|
||||
public string Id { get; set; }
|
||||
|
||||
[Column("parent_call_id")]
|
||||
public string ParentCallId { get; set; }
|
||||
|
||||
[Column("number_from")]
|
||||
public string NumberFrom { get; set; }
|
||||
|
||||
[Column("number_to")]
|
||||
public string NumberTo { get; set; }
|
||||
public int Status { get; set; }
|
||||
|
||||
[Column("answered_by")]
|
||||
public Guid AnsweredBy { get; set; }
|
||||
|
||||
[Column("dial_date")]
|
||||
public DateTime DialDate { get; set; }
|
||||
|
||||
[Column("dial_duration")]
|
||||
public int DialDuration { get; set; }
|
||||
|
||||
[Column("record_sid")]
|
||||
public string RecordSid { get; set; }
|
||||
|
||||
[Column("record_url")]
|
||||
public string RecordUrl { get; set; }
|
||||
|
||||
[Column("record_duration")]
|
||||
public int RecordDuration { get; set; }
|
||||
|
||||
[Column("record_price")]
|
||||
public decimal RecordPrice { get; set; }
|
||||
|
||||
[Column("contact_id")]
|
||||
public int ContactId { get; set; }
|
||||
|
||||
public decimal Price { get; set; }
|
||||
|
||||
[Column("tenant_id")]
|
||||
public int TenantId { get; set; }
|
||||
|
||||
public CrmContact CrmContact { get; set; }
|
||||
}
|
||||
}
|
16
common/ASC.Core.Common/EF/Model/VoipNumber.cs
Normal file
16
common/ASC.Core.Common/EF/Model/VoipNumber.cs
Normal file
@ -0,0 +1,16 @@
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
|
||||
namespace ASC.Core.Common.EF.Model
|
||||
{
|
||||
[Table("crm_voip_number")]
|
||||
public class VoipNumber
|
||||
{
|
||||
public string Id { get; set; }
|
||||
public string Number { get; set; }
|
||||
public string Alias { get; set; }
|
||||
public string Settings { get; set; }
|
||||
|
||||
[Column("tenant_id")]
|
||||
public int TenantId { get; set; }
|
||||
}
|
||||
}
|
@ -25,9 +25,11 @@
|
||||
|
||||
|
||||
using System;
|
||||
|
||||
using ASC.Common.Data;
|
||||
using ASC.Common.Data.Sql;
|
||||
|
||||
using ASC.Core.Common.EF;
|
||||
using ASC.Core.Common.EF.Context;
|
||||
|
||||
namespace ASC.VoipService.Dao
|
||||
{
|
||||
@ -35,9 +37,11 @@ namespace ASC.VoipService.Dao
|
||||
{
|
||||
private readonly string dbid = "default";
|
||||
|
||||
protected AbstractDao(DbOptionsManager dbOptions, int tenantID)
|
||||
protected VoipDbContext VoipDbContext { get; set; }
|
||||
|
||||
protected AbstractDao(DbContextManager<VoipDbContext> dbOptions, int tenantID)
|
||||
{
|
||||
DbOptions = dbOptions;
|
||||
VoipDbContext = dbOptions.Get(dbid);
|
||||
TenantID = tenantID;
|
||||
}
|
||||
|
||||
|
@ -28,10 +28,12 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
|
||||
using ASC.Common.Caching;
|
||||
using ASC.Common.Data;
|
||||
using ASC.Core;
|
||||
using ASC.Core.Common;
|
||||
using ASC.Core.Common.EF;
|
||||
using ASC.Core.Common.EF.Context;
|
||||
using ASC.Core.Tenants;
|
||||
|
||||
namespace ASC.VoipService.Dao
|
||||
@ -63,7 +65,7 @@ namespace ASC.VoipService.Dao
|
||||
|
||||
public CachedVoipDao(
|
||||
int tenantID,
|
||||
DbOptionsManager dbOptions,
|
||||
DbContextManager<VoipDbContext> dbOptions,
|
||||
AuthContext authContext,
|
||||
TenantUtil tenantUtil,
|
||||
SecurityContext securityContext,
|
||||
@ -88,7 +90,7 @@ namespace ASC.VoipService.Dao
|
||||
VoipDaoCache.ResetCache(TenantID);
|
||||
}
|
||||
|
||||
public override IEnumerable<VoipPhone> GetNumbers(params object[] ids)
|
||||
public override IEnumerable<VoipPhone> GetNumbers(params string[] ids)
|
||||
{
|
||||
var numbers = cache.Get<List<VoipPhone>>(GetCacheKey(TenantID));
|
||||
if (numbers == null)
|
||||
|
@ -27,12 +27,13 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using ASC.Common.Data;
|
||||
using ASC.Common.Data.Sql;
|
||||
using ASC.Common.Data.Sql.Expressions;
|
||||
|
||||
using ASC.Core;
|
||||
using ASC.Core.Common;
|
||||
using ASC.Core.Common.Configuration;
|
||||
using ASC.Core.Common.EF;
|
||||
using ASC.Core.Common.EF.Context;
|
||||
using ASC.Core.Common.EF.Model;
|
||||
using ASC.Core.Tenants;
|
||||
using ASC.VoipService.Twilio;
|
||||
|
||||
@ -40,7 +41,7 @@ namespace ASC.VoipService.Dao
|
||||
{
|
||||
public class VoipDao : AbstractDao
|
||||
{
|
||||
public VoipDao(int tenantID, DbOptionsManager dbOptions, AuthContext authContext, TenantUtil tenantUtil, SecurityContext securityContext, BaseCommonLinkUtility baseCommonLinkUtility)
|
||||
public VoipDao(int tenantID, DbContextManager<VoipDbContext> dbOptions, AuthContext authContext, TenantUtil tenantUtil, SecurityContext securityContext, BaseCommonLinkUtility baseCommonLinkUtility)
|
||||
: base(dbOptions, tenantID)
|
||||
{
|
||||
AuthContext = authContext;
|
||||
@ -56,46 +57,38 @@ namespace ASC.VoipService.Dao
|
||||
phone.Number = phone.Number.TrimStart('+');
|
||||
}
|
||||
|
||||
using (var db = GetDb())
|
||||
var voipNumber = new VoipNumber
|
||||
{
|
||||
var insert = Insert("crm_voip_number")
|
||||
.InColumnValue("id", phone.Id)
|
||||
.InColumnValue("number", phone.Number)
|
||||
.InColumnValue("alias", phone.Alias);
|
||||
Id = phone.Id,
|
||||
Number = phone.Number,
|
||||
Alias = phone.Alias,
|
||||
Settings = phone.Settings.ToString(),
|
||||
TenantId = TenantID
|
||||
};
|
||||
|
||||
if (phone.Settings != null)
|
||||
{
|
||||
insert.InColumnValue("settings", phone.Settings.ToString());
|
||||
}
|
||||
VoipDbContext.VoipNumbers.Add(voipNumber);
|
||||
VoipDbContext.SaveChanges();
|
||||
|
||||
db.ExecuteNonQuery(insert);
|
||||
}
|
||||
return phone;
|
||||
}
|
||||
|
||||
public virtual void DeleteNumber(string phoneId = "")
|
||||
{
|
||||
using var db = GetDb();
|
||||
var query = Delete("crm_voip_number");
|
||||
if (!string.IsNullOrEmpty(phoneId))
|
||||
{
|
||||
query.Where("id", phoneId);
|
||||
}
|
||||
db.ExecuteNonQuery(query);
|
||||
var number = VoipDbContext.VoipNumbers.Where(r => r.Id == phoneId && r.TenantId == TenantID).FirstOrDefault();
|
||||
VoipDbContext.VoipNumbers.Remove(number);
|
||||
VoipDbContext.SaveChanges();
|
||||
}
|
||||
|
||||
public virtual IEnumerable<VoipPhone> GetNumbers(params object[] ids)
|
||||
public virtual IEnumerable<VoipPhone> GetNumbers(params string[] ids)
|
||||
{
|
||||
using var db = GetDb();
|
||||
var query = Query("crm_voip_number")
|
||||
.Select("id", "number", "alias", "settings");
|
||||
var numbers = VoipDbContext.VoipNumbers.Where(r => r.TenantId == TenantID);
|
||||
|
||||
if (ids.Any())
|
||||
{
|
||||
query.Where(Exp.In("number", ids) | Exp.In("id", ids));
|
||||
numbers = numbers.Where(r => ids.Any(a => a == r.Number || a == r.Id));
|
||||
}
|
||||
|
||||
return db.ExecuteList(query).ConvertAll(ToPhone);
|
||||
return numbers.ToList().ConvertAll(ToPhone);
|
||||
}
|
||||
|
||||
public VoipPhone GetNumber(string id)
|
||||
@ -111,27 +104,30 @@ namespace ASC.VoipService.Dao
|
||||
|
||||
public VoipCall SaveOrUpdateCall(VoipCall call)
|
||||
{
|
||||
var voipCall = new DbVoipCall
|
||||
{
|
||||
TenantId = TenantID,
|
||||
Id = call.Id,
|
||||
NumberFrom = call.From,
|
||||
NumberTo = call.To,
|
||||
ContactId = call.ContactId
|
||||
};
|
||||
|
||||
using (var db = GetDb())
|
||||
{
|
||||
var query = Insert("crm_voip_calls")
|
||||
.InColumnValue("id", call.Id)
|
||||
.InColumnValue("number_from", call.From)
|
||||
.InColumnValue("number_to", call.To)
|
||||
.InColumnValue("contact_id", call.ContactId);
|
||||
|
||||
if (!string.IsNullOrEmpty(call.ParentID))
|
||||
{
|
||||
query.InColumnValue("parent_call_id", call.ParentID);
|
||||
voipCall.ParentCallId = call.ParentID;
|
||||
}
|
||||
|
||||
if (call.Status.HasValue)
|
||||
{
|
||||
query.InColumnValue("status", call.Status.Value);
|
||||
voipCall.Status = (int)call.Status.Value;
|
||||
}
|
||||
|
||||
if (!call.AnsweredBy.Equals(Guid.Empty))
|
||||
{
|
||||
query.InColumnValue("answered_by", call.AnsweredBy);
|
||||
voipCall.AnsweredBy = call.AnsweredBy;
|
||||
}
|
||||
|
||||
if (call.DialDate == DateTime.MinValue)
|
||||
@ -139,40 +135,43 @@ namespace ASC.VoipService.Dao
|
||||
call.DialDate = DateTime.UtcNow;
|
||||
}
|
||||
|
||||
query.InColumnValue("dial_date", TenantUtil.DateTimeToUtc(call.DialDate));
|
||||
voipCall.DialDate = TenantUtil.DateTimeToUtc(call.DialDate);
|
||||
|
||||
if (call.DialDuration > 0)
|
||||
{
|
||||
query.InColumnValue("dial_duration", call.DialDuration);
|
||||
voipCall.DialDuration = call.DialDuration;
|
||||
}
|
||||
|
||||
if (call.Price > decimal.Zero)
|
||||
{
|
||||
query.InColumnValue("price", call.Price);
|
||||
voipCall.Price = call.Price;
|
||||
}
|
||||
|
||||
if (call.VoipRecord != null)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(call.VoipRecord.Id))
|
||||
{
|
||||
query.InColumnValue("record_sid", call.VoipRecord.Id);
|
||||
voipCall.RecordSid = call.VoipRecord.Id;
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(call.VoipRecord.Uri))
|
||||
{
|
||||
query.InColumnValue("record_url", call.VoipRecord.Uri);
|
||||
voipCall.RecordUrl = call.VoipRecord.Uri;
|
||||
}
|
||||
|
||||
if (call.VoipRecord.Duration != 0)
|
||||
{
|
||||
query.InColumnValue("record_duration", call.VoipRecord.Duration);
|
||||
voipCall.RecordDuration = call.VoipRecord.Duration;
|
||||
}
|
||||
|
||||
if (call.VoipRecord.Price != default)
|
||||
{
|
||||
query.InColumnValue("record_price", call.VoipRecord.Price);
|
||||
voipCall.RecordPrice = call.VoipRecord.Price;
|
||||
}
|
||||
}
|
||||
|
||||
db.ExecuteNonQuery(query);
|
||||
VoipDbContext.VoipCalls.Add(voipCall);
|
||||
VoipDbContext.SaveChanges();
|
||||
}
|
||||
|
||||
return call;
|
||||
@ -180,7 +179,6 @@ namespace ASC.VoipService.Dao
|
||||
|
||||
public IEnumerable<VoipCall> GetCalls(VoipCallFilter filter)
|
||||
{
|
||||
using var db = GetDb();
|
||||
var query = GetCallsQuery(filter);
|
||||
|
||||
if (filter.SortByColumn != null)
|
||||
@ -188,10 +186,10 @@ namespace ASC.VoipService.Dao
|
||||
query.OrderBy(filter.SortByColumn, filter.SortOrder);
|
||||
}
|
||||
|
||||
query.SetFirstResult((int)filter.Offset);
|
||||
query.SetMaxResults((int)filter.Max * 3);
|
||||
query = query.Skip((int)filter.Offset);
|
||||
query = query.Take((int)filter.Max * 3);
|
||||
|
||||
var calls = db.ExecuteList(query).ConvertAll(ToCall);
|
||||
var calls = query.ToList().ConvertAll(ToCall);
|
||||
|
||||
calls = calls.GroupJoin(calls, call => call.Id, h => h.ParentID, (call, h) =>
|
||||
{
|
||||
@ -209,11 +207,7 @@ namespace ASC.VoipService.Dao
|
||||
|
||||
public int GetCallsCount(VoipCallFilter filter)
|
||||
{
|
||||
using var db = GetDb();
|
||||
var query = GetCallsQuery(filter).Where("ca.parent_call_id", "");
|
||||
var queryCount = new SqlQuery().SelectCount().From(query, "t1");
|
||||
|
||||
return db.ExecuteScalar<int>(queryCount);
|
||||
return GetCallsQuery(filter).Where(r => r.DbVoipCall.ParentCallId == "").Count();
|
||||
}
|
||||
|
||||
public IEnumerable<VoipCall> GetMissedCalls(Guid agent, long count = 0, DateTime? from = null)
|
||||
@ -221,113 +215,121 @@ namespace ASC.VoipService.Dao
|
||||
using var db = GetDb();
|
||||
var query = GetCallsQuery(new VoipCallFilter { Agent = agent, SortBy = "date", SortOrder = true, Type = "missed" });
|
||||
|
||||
var subQuery = new SqlQuery("crm_voip_calls tmp")
|
||||
.SelectMax("tmp.dial_date")
|
||||
.Where(Exp.EqColumns("ca.tenant_id", "tmp.tenant_id"))
|
||||
.Where(Exp.EqColumns("ca.number_from", "tmp.number_from") | Exp.EqColumns("ca.number_from", "tmp.number_to"))
|
||||
.Where(Exp.Lt("tmp.status", VoipCallStatus.Missed));
|
||||
|
||||
if (from.HasValue)
|
||||
{
|
||||
query.Where(Exp.Ge("ca.dial_date", TenantUtil.DateTimeFromUtc(from.Value)));
|
||||
query = query.Where(r => r.DbVoipCall.DialDate >= TenantUtil.DateTimeFromUtc(from.Value));
|
||||
}
|
||||
|
||||
if (count != 0)
|
||||
{
|
||||
query.SetMaxResults((int)count);
|
||||
query = query.Take((int)count);
|
||||
}
|
||||
|
||||
query.Select(subQuery, "tmp_date");
|
||||
|
||||
query.Having(Exp.Sql("ca.dial_date >= tmp_date") | Exp.Eq("tmp_date", null));
|
||||
|
||||
return db.ExecuteList(query).ConvertAll(ToCall);
|
||||
}
|
||||
|
||||
private SqlQuery GetCallsQuery(VoipCallFilter filter)
|
||||
var a = query.Select(ca => new
|
||||
{
|
||||
var query = Query("crm_voip_calls ca")
|
||||
.Select("ca.id", "ca.parent_call_id", "ca.number_from", "ca.number_to", "ca.answered_by", "ca.dial_date", "ca.dial_duration", "ca.price", "ca.status")
|
||||
.Select("ca.record_sid", "ca.record_url", "ca.record_duration", "ca.record_price")
|
||||
.Select("ca.contact_id", "co.is_company", "co.company_name", "co.first_name", "co.last_name")
|
||||
.LeftOuterJoin("crm_contact co", Exp.EqColumns("ca.contact_id", "co.id"))
|
||||
.GroupBy("ca.id");
|
||||
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);
|
||||
|
||||
return a.ToList().ConvertAll(r => ToCall(r.dbVoipCall));
|
||||
}
|
||||
|
||||
private IQueryable<CallContact> GetCallsQuery(VoipCallFilter filter)
|
||||
{
|
||||
var q = VoipDbContext.VoipCalls
|
||||
.Where(r => r.TenantId == TenantID);
|
||||
|
||||
if (!string.IsNullOrEmpty(filter.Id))
|
||||
{
|
||||
query.Where(Exp.Eq("ca.id", filter.Id) | Exp.Eq("ca.parent_call_id", filter.Id));
|
||||
q = q.Where(r => r.Id == filter.Id || r.ParentCallId == filter.Id);
|
||||
}
|
||||
|
||||
if (filter.ContactID.HasValue)
|
||||
{
|
||||
query.Where(Exp.Eq("ca.contact_id", filter.ContactID.Value));
|
||||
q = q.Where(r => r.ContactId == filter.ContactID.Value);
|
||||
}
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(filter.SearchText))
|
||||
{
|
||||
query.Where(Exp.Like("ca.id", filter.SearchText, SqlLike.StartWith));
|
||||
q = q.Where(r => r.Id.StartsWith(filter.SearchText));
|
||||
}
|
||||
|
||||
if (filter.TypeStatus.HasValue)
|
||||
{
|
||||
query.Where("ca.status", filter.TypeStatus.Value);
|
||||
q = q.Where(r => r.Status == filter.TypeStatus.Value);
|
||||
}
|
||||
|
||||
if (filter.FromDate.HasValue)
|
||||
{
|
||||
query.Where(Exp.Ge("ca.dial_date", filter.FromDate.Value));
|
||||
q = q.Where(r => r.DialDate >= filter.FromDate.Value);
|
||||
}
|
||||
|
||||
if (filter.ToDate.HasValue)
|
||||
{
|
||||
query.Where(Exp.Le("ca.dial_date", filter.ToDate.Value));
|
||||
q = q.Where(r => r.DialDate <= filter.ToDate.Value);
|
||||
}
|
||||
|
||||
if (filter.Agent.HasValue)
|
||||
{
|
||||
query.Where("ca.answered_by", filter.Agent.Value);
|
||||
q = q.Where(r => r.AnsweredBy == filter.Agent.Value);
|
||||
}
|
||||
|
||||
return query;
|
||||
return q
|
||||
.GroupBy(r => r.Id, r => r)
|
||||
.Join(
|
||||
VoipDbContext.CrmContact.DefaultIfEmpty(),
|
||||
r => r.FirstOrDefault().ContactId,
|
||||
c => c.Id,
|
||||
(call, contact) => new CallContact { DbVoipCall = call.FirstOrDefault(), CrmContact = contact })
|
||||
;
|
||||
}
|
||||
|
||||
class CallContact
|
||||
{
|
||||
public DbVoipCall DbVoipCall { get; set; }
|
||||
public CrmContact CrmContact { get; set; }
|
||||
}
|
||||
|
||||
#region Converters
|
||||
|
||||
private VoipPhone ToPhone(object[] r)
|
||||
private VoipPhone ToPhone(VoipNumber r)
|
||||
{
|
||||
return GetProvider(AuthContext, TenantUtil, SecurityContext, BaseCommonLinkUtility).GetPhone(r);
|
||||
}
|
||||
|
||||
private VoipCall ToCall(object[] r)
|
||||
private VoipCall ToCall(CallContact dbVoipCall)
|
||||
{
|
||||
var call = new VoipCall
|
||||
{
|
||||
Id = (string)r[0],
|
||||
ParentID = (string)r[1],
|
||||
From = (string)r[2],
|
||||
To = (string)r[3],
|
||||
AnsweredBy = new Guid((string)r[4]),
|
||||
DialDate = TenantUtil.DateTimeFromUtc(Convert.ToDateTime(r[5])),
|
||||
DialDuration = Convert.ToInt32(r[6] ?? "0"),
|
||||
Price = Convert.ToDecimal(r[7]),
|
||||
Status = (VoipCallStatus)Convert.ToInt32(r[8]),
|
||||
Id = dbVoipCall.DbVoipCall.Id,
|
||||
ParentID = dbVoipCall.DbVoipCall.ParentCallId,
|
||||
From = dbVoipCall.DbVoipCall.NumberFrom,
|
||||
To = dbVoipCall.DbVoipCall.NumberTo,
|
||||
AnsweredBy = dbVoipCall.DbVoipCall.AnsweredBy,
|
||||
DialDate = TenantUtil.DateTimeFromUtc(dbVoipCall.DbVoipCall.DialDate),
|
||||
DialDuration = dbVoipCall.DbVoipCall.DialDuration,
|
||||
Price = dbVoipCall.DbVoipCall.Price,
|
||||
Status = (VoipCallStatus)dbVoipCall.DbVoipCall.Status,
|
||||
VoipRecord = new VoipRecord
|
||||
{
|
||||
Id = (string)r[9],
|
||||
Uri = (string)r[10],
|
||||
Duration = Convert.ToInt32(r[11] ?? "0"),
|
||||
Price = Convert.ToDecimal(r[12])
|
||||
Id = dbVoipCall.DbVoipCall.RecordSid,
|
||||
Uri = dbVoipCall.DbVoipCall.RecordUrl,
|
||||
Duration = dbVoipCall.DbVoipCall.RecordDuration,
|
||||
Price = dbVoipCall.DbVoipCall.RecordPrice
|
||||
},
|
||||
ContactId = Convert.ToInt32(r[13]),
|
||||
ContactIsCompany = Convert.ToBoolean(r[14])
|
||||
ContactId = dbVoipCall.CrmContact.Id,
|
||||
ContactIsCompany = dbVoipCall.CrmContact.IsCompany,
|
||||
};
|
||||
|
||||
if (call.ContactId != 0)
|
||||
{
|
||||
call.ContactTitle = call.ContactIsCompany
|
||||
? r[15] == null ? null : Convert.ToString(r[15])
|
||||
: r[16] == null || r[17] == null ? null :
|
||||
string.Format("{0} {1}", Convert.ToString(r[16]), Convert.ToString(r[17]));
|
||||
? dbVoipCall.CrmContact.CompanyName
|
||||
: dbVoipCall.CrmContact.FirstName == null || dbVoipCall.CrmContact.LastName == null ? null : string.Format("{0} {1}", dbVoipCall.CrmContact.FirstName, dbVoipCall.CrmContact.LastName);
|
||||
}
|
||||
|
||||
return call;
|
||||
|
@ -25,6 +25,8 @@
|
||||
|
||||
|
||||
using System.Collections.Generic;
|
||||
|
||||
using ASC.Core.Common.EF.Model;
|
||||
using ASC.VoipService.Twilio;
|
||||
|
||||
namespace ASC.VoipService
|
||||
@ -39,7 +41,7 @@ namespace ASC.VoipService
|
||||
|
||||
VoipPhone DeleteNumber(VoipPhone phone);
|
||||
|
||||
VoipPhone GetPhone(object[] r);
|
||||
VoipPhone GetPhone(VoipNumber r);
|
||||
|
||||
VoipPhone GetPhone(string id);
|
||||
|
||||
|
@ -28,9 +28,12 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
|
||||
using ASC.Core;
|
||||
using ASC.Core.Common;
|
||||
using ASC.Core.Common.EF.Model;
|
||||
using ASC.Core.Tenants;
|
||||
|
||||
using Twilio.Clients;
|
||||
using Twilio.Exceptions;
|
||||
using Twilio.Jwt;
|
||||
@ -38,6 +41,7 @@ using Twilio.Jwt.Client;
|
||||
using Twilio.Rest.Api.V2010.Account;
|
||||
using Twilio.Rest.Api.V2010.Account.AvailablePhoneNumberCountry;
|
||||
using Twilio.Types;
|
||||
|
||||
using RecordingResource = Twilio.Rest.Api.V2010.Account.Call.RecordingResource;
|
||||
|
||||
|
||||
@ -171,14 +175,14 @@ namespace ASC.VoipService.Twilio
|
||||
return result;
|
||||
}
|
||||
|
||||
public VoipPhone GetPhone(object[] data)
|
||||
public VoipPhone GetPhone(VoipNumber data)
|
||||
{
|
||||
return new TwilioPhone(client, AuthContext, TenantUtil, SecurityContext, BaseCommonLinkUtility)
|
||||
{
|
||||
Id = (string)data[0],
|
||||
Number = (string)data[1],
|
||||
Alias = (string)data[2],
|
||||
Settings = new TwilioVoipSettings((string)data[3], AuthContext)
|
||||
Id = data.Id,
|
||||
Number = data.Number,
|
||||
Alias = data.Alias,
|
||||
Settings = new TwilioVoipSettings(data.Settings, AuthContext)
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -31,17 +31,21 @@ using System.IO;
|
||||
using System.Net;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Web;
|
||||
|
||||
using ASC.Common.Caching;
|
||||
using ASC.Common.Data;
|
||||
using ASC.Common.Logging;
|
||||
using ASC.Core;
|
||||
using ASC.Core.Common;
|
||||
using ASC.Core.Common.Configuration;
|
||||
using ASC.Core.Common.EF;
|
||||
using ASC.Core.Common.EF.Context;
|
||||
using ASC.Core.Tenants;
|
||||
using ASC.FederatedLogin.LoginProviders;
|
||||
using ASC.VoipService.Dao;
|
||||
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.Options;
|
||||
|
||||
using Twilio.Clients;
|
||||
using Twilio.Rest.Api.V2010.Account;
|
||||
using Twilio.Types;
|
||||
@ -442,7 +446,7 @@ namespace ASC.Web.Core.Sms
|
||||
}
|
||||
}
|
||||
|
||||
public void ClearOldNumbers(DbOptionsManager dbOptions, AuthContext authContext, TenantUtil tenantUtil, SecurityContext securityContext, TenantManager tenantManager, BaseCommonLinkUtility baseCommonLinkUtility, VoipDaoCache voipDaoCache)
|
||||
public void ClearOldNumbers(DbContextManager<VoipDbContext> dbOptions, AuthContext authContext, TenantUtil tenantUtil, SecurityContext securityContext, TenantManager tenantManager, BaseCommonLinkUtility baseCommonLinkUtility, VoipDaoCache voipDaoCache)
|
||||
{
|
||||
if (string.IsNullOrEmpty(Key) || string.IsNullOrEmpty(Secret)) return;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user