/* * * (c) Copyright Ascensio System Limited 2010-2018 * * This program is freeware. You can redistribute it and/or modify it under the terms of the GNU * General Public License (GPL) version 3 as published by the Free Software Foundation (https://www.gnu.org/copyleft/gpl.html). * In accordance with Section 7(a) of the GNU GPL its Section 15 shall be amended to the effect that * Ascensio System SIA expressly excludes the warranty of non-infringement of any third-party rights. * * THIS PROGRAM IS DISTRIBUTED WITHOUT ANY WARRANTY; WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR * FITNESS FOR A PARTICULAR PURPOSE. For more details, see GNU GPL at https://www.gnu.org/copyleft/gpl.html * * You can contact Ascensio System SIA by email at sales@onlyoffice.com * * The interactive user interfaces in modified source and object code versions of ONLYOFFICE must display * Appropriate Legal Notices, as required under Section 5 of the GNU GPL version 3. * * Pursuant to Section 7 § 3(b) of the GNU GPL you must retain the original ONLYOFFICE logo which contains * relevant author attributions when distributing the software. If the display of the logo in its graphic * form is not reasonably feasible for technical reasons, you must include the words "Powered by ONLYOFFICE" * in every copy of the program you distribute. * Pursuant to Section 7 § 3(e) we decline to grant you any rights under trademark law for use of our trademarks. * */ namespace ASC.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 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 GetAllNumbers() { return VoipDbContext.VoipNumbers .Where(r => r.TenantId == TenantID) .ToList() .ConvertAll(ToPhone); } public virtual IEnumerable 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 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, IEnumerable>(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 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, IEnumerable>(query.ToList()); } private IQueryable 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; } }