DocSpace-buildtools/products/ASC.CRM/Server/Api/VoipController.cs
2021-03-19 19:56:26 +03:00

983 lines
36 KiB
C#

/*
*
* (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.Globalization;
using System.IO;
using System.Linq;
using System.Security;
using ASC.Api.Core;
using ASC.Api.CRM;
using ASC.Api.Utils;
using ASC.Common.Web;
using ASC.Core.Notify.Signalr;
using ASC.Core.Tenants;
using ASC.CRM.ApiModels;
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.Data.Storage;
using ASC.VoipService;
using ASC.VoipService.Dao;
using ASC.VoipService.Twilio;
using ASC.Web.Api.Routing;
using ASC.Web.CRM.Classes;
using ASC.Web.Studio.Utility;
using AutoMapper;
using SecurityContext = ASC.Core.SecurityContext;
namespace ASC.CRM.Api
{
public class VoIPController : BaseApiController
{
public VoIPController(CRMSecurity cRMSecurity,
DaoFactory daoFactory,
Global global,
ContactPhotoManager contactPhotoManager,
StorageFactory storageFactory,
CommonLinkUtility commonLinkUtility,
SecurityContext securityContext,
VoipCallDtoHelper voipCallDtoHelper,
TenantUtil tenantUtil,
VoipEngine voipEngine,
ApiContext apiContext,
SignalrServiceClient signalrServiceClient,
IMapper mapper)
: base(daoFactory, cRMSecurity, mapper)
{
Global = global;
ContactPhotoManager = contactPhotoManager;
StorageFactory = storageFactory;
CommonLinkUtility = commonLinkUtility;
SecurityContext = securityContext;
VoipCallDtoHelper = voipCallDtoHelper;
TenantUtil = tenantUtil;
VoipEngine = voipEngine;
ApiContext = apiContext;
SignalrServiceClient = signalrServiceClient;
}
public SignalrServiceClient SignalrServiceClient { get; }
public ApiContext ApiContext { get; }
public VoipEngine VoipEngine { get; }
public TenantUtil TenantUtil { get; }
public VoipCallDtoHelper VoipCallDtoHelper { get; }
public SecurityContext SecurityContext { get; }
public CommonLinkUtility CommonLinkUtility { get; }
public StorageFactory StorageFactory { get; }
public ContactPhotoManager ContactPhotoManager { get; }
public Global Global { get; }
/// <summary>
///
/// </summary>
/// <short></short>
/// <category>Voip</category>
/// <returns></returns>
/// <exception cref="SecurityException"></exception>
/// <exception cref="ArgumentException"></exception>
[Read(@"voip/numbers/available")]
public IEnumerable<VoipPhone> GetAvailablePhoneNumbers(PhoneNumberType numberType, string isoCountryCode)
{
if (!_crmSecurity.IsAdmin) throw _crmSecurity.CreateSecurityException();
if (string.IsNullOrEmpty(isoCountryCode)) throw new ArgumentException();
return _daoFactory.GetVoipDao().GetProvider().GetAvailablePhoneNumbers(numberType, isoCountryCode);
}
/// <summary>
///
/// </summary>
/// <short></short>
/// <category>Voip</category>
/// <returns></returns>
/// <exception cref="SecurityException"></exception>
[Read(@"voip/numbers/unlinked")]
public IEnumerable<VoipPhone> GetUnlinkedPhoneNumbers()
{
if (!_crmSecurity.IsAdmin) throw _crmSecurity.CreateSecurityException();
var listPhones = _daoFactory.GetVoipDao().GetProvider().GetExistingPhoneNumbers();
var buyedPhones = _daoFactory.GetVoipDao().GetNumbers();
return listPhones.Where(r => buyedPhones.All(b => r.Id != b.Id)).ToList();
}
/// <summary>
///
/// </summary>
/// <short></short>
/// <category>Voip</category>
/// <returns></returns>
/// <exception cref="SecurityException"></exception>
[Read(@"voip/numbers/existing")]
public IEnumerable<VoipPhone> GetExistingPhoneNumbers()
{
if (!_crmSecurity.IsAdmin) throw _crmSecurity.CreateSecurityException();
return _daoFactory.GetVoipDao().GetNumbers();
}
/// <summary>
///
/// </summary>
/// <short></short>
/// <category>Voip</category>
/// <returns></returns>
/// <exception cref="SecurityException"></exception>
[Create(@"voip/numbers")]
public VoipPhone BuyNumber(string number)
{
if (!_crmSecurity.IsAdmin) throw _crmSecurity.CreateSecurityException();
var newPhone = _daoFactory.GetVoipDao().GetProvider().BuyNumber(number);
_daoFactory.GetVoipDao().GetProvider().CreateQueue(newPhone);
SetDefaultAudio(newPhone);
_daoFactory.GetVoipDao().GetProvider().UpdateSettings(newPhone);
return _daoFactory.GetVoipDao().SaveOrUpdateNumber(newPhone);
}
/// <summary>
///
/// </summary>
/// <short></short>
/// <category>Voip</category>
/// <returns></returns>
/// <exception cref="SecurityException"></exception>
[Create(@"voip/numbers/link")]
public VoipPhone LinkNumber(string id)
{
if (!_crmSecurity.IsAdmin) throw _crmSecurity.CreateSecurityException();
var newPhone = _daoFactory.GetVoipDao().GetProvider().GetPhone(id);
_daoFactory.GetVoipDao().GetProvider().CreateQueue(newPhone);
SetDefaultAudio(newPhone);
_daoFactory.GetVoipDao().GetProvider().UpdateSettings(newPhone);
return _daoFactory.GetVoipDao().SaveOrUpdateNumber(newPhone);
}
public void SetDefaultAudio(VoipPhone newPhone)
{
var storage = StorageFactory.GetStorage("", "crm");
const string path = "default/";
var files = storage.ListFilesRelative("voip", path, "*.*", true)
.Select(filePath => new
{
path = CommonLinkUtility.GetFullAbsolutePath(storage.GetUri("voip", Path.Combine(path, filePath)).ToString()),
audioType = (AudioType)Enum.Parse(typeof(AudioType), Directory.GetParent(filePath).Name, true)
}).ToList();
var audio = files.Find(r => r.audioType == AudioType.Greeting);
newPhone.Settings.GreetingAudio = audio != null ? audio.path : "";
audio = files.Find(r => r.audioType == AudioType.HoldUp);
newPhone.Settings.HoldAudio = audio != null ? audio.path : "";
audio = files.Find(r => r.audioType == AudioType.VoiceMail);
newPhone.Settings.VoiceMail = audio != null ? audio.path : "";
audio = files.Find(r => r.audioType == AudioType.Queue);
newPhone.Settings.Queue.WaitUrl = audio != null ? audio.path : "";
}
/// <summary>
///
/// </summary>
/// <short></short>
/// <category>Voip</category>
/// <returns></returns>
/// <exception cref="SecurityException"></exception>
[Delete(@"voip/numbers/{numberId:regex(\w+)}")]
public VoipPhone DeleteNumber(string numberId)
{
if (!_crmSecurity.IsAdmin) throw _crmSecurity.CreateSecurityException();
var dao = _daoFactory.GetVoipDao();
var phone = dao.GetNumber(numberId).NotFoundIfNull();
_daoFactory.GetVoipDao().GetProvider().DisablePhone(phone);
dao.DeleteNumber(numberId);
new SignalRHelper(phone.Number, SignalrServiceClient).Reload();
return phone;
}
/// <summary>
///
/// </summary>
/// <short></short>
/// <category>Voip</category>
/// <returns></returns>
/// <exception cref="SecurityException"></exception>
[Read(@"voip/numbers/{numberId:regex(\w+)}")]
public VoipPhone GetNumber(string numberId)
{
return _daoFactory.GetVoipDao().GetNumber(numberId).NotFoundIfNull();
}
/// <summary>
///
/// </summary>
/// <short></short>
/// <category>Voip</category>
/// <returns></returns>
[Read(@"voip/numbers/current")]
public VoipPhone GetCurrentNumber()
{
return _daoFactory.GetVoipDao().GetCurrentNumber().NotFoundIfNull();
}
/// <summary>
///
/// </summary>
/// <short></short>
/// <category>Voip</category>
/// <returns></returns>
[Read(@"voip/token")]
public string GetToken()
{
return _daoFactory.GetVoipDao().GetProvider().GetToken(GetCurrentNumber().Caller);
}
/// <summary>
///
/// </summary>
/// <short></short>
/// <category>Voip</category>
/// <returns></returns>
/// <exception cref="SecurityException"></exception>
[Update(@"voip/numbers/{numberId:regex(\w+)}/settings")]
public VoipPhone UpdateSettings(string numberId, string greeting, string holdUp, string wait, string voiceMail, WorkingHours workingHours, bool? allowOutgoingCalls, bool? record, string alias)
{
if (!_crmSecurity.IsAdmin) throw _crmSecurity.CreateSecurityException();
var dao = _daoFactory.GetVoipDao();
var number = dao.GetNumber(numberId).NotFoundIfNull();
number.Alias = Update.IfNotEmptyAndNotEquals(number.Alias, alias);
number.Settings.GreetingAudio = Update.IfNotEmptyAndNotEquals(number.Settings.GreetingAudio, greeting);
number.Settings.HoldAudio = Update.IfNotEmptyAndNotEquals(number.Settings.HoldAudio, holdUp);
number.Settings.VoiceMail = Update.IfNotEmptyAndNotEquals(number.Settings.VoiceMail, voiceMail);
number.Settings.WorkingHours = Update.IfNotEmptyAndNotEquals(number.Settings.WorkingHours, workingHours);
if (!string.IsNullOrEmpty(wait))
{
number.Settings.Queue.WaitUrl = wait;
}
if (allowOutgoingCalls.HasValue)
{
number.Settings.AllowOutgoingCalls = allowOutgoingCalls.Value;
if (!number.Settings.AllowOutgoingCalls)
{
number.Settings.Operators.ForEach(r => r.AllowOutgoingCalls = false);
}
}
if (record.HasValue)
{
number.Settings.Record = record.Value;
if (!number.Settings.Record)
{
number.Settings.Operators.ForEach(r => r.Record = false);
}
}
dao.SaveOrUpdateNumber(number);
return number;
}
/// <summary>
///
/// </summary>
/// <short></short>
/// <category>Voip</category>
/// <returns></returns>
/// <exception cref="SecurityException"></exception>
[Update(@"voip/numbers/settings")]
public object UpdateSettings(Queue queue, bool pause)
{
if (!_crmSecurity.IsAdmin) throw _crmSecurity.CreateSecurityException();
var dao = _daoFactory.GetVoipDao();
var numbers = dao.GetNumbers();
if (queue != null)
{
foreach (var number in numbers)
{
if (number.Settings.Queue == null || string.IsNullOrEmpty(number.Settings.Queue.Id))
{
var phone = number as TwilioPhone;
if (phone != null)
{
queue = phone.CreateQueue(phone.Number, queue.Size, queue.WaitUrl, queue.WaitTime * 60);
}
queue.Name = number.Number;
number.Settings.Queue = queue;
}
else
{
var oldQueue = number.Settings.Queue;
oldQueue.Size = Update.IfNotEmptyAndNotEquals(oldQueue.Size, queue.Size);
oldQueue.WaitTime = Update.IfNotEmptyAndNotEquals(oldQueue.WaitTime, queue.WaitTime * 60);
oldQueue.WaitUrl = Update.IfNotEmptyAndNotEquals(oldQueue.WaitUrl, queue.WaitUrl);
}
number.Settings.Pause = pause;
dao.SaveOrUpdateNumber(number);
}
}
return new { queue, pause };
}
/// <summary>
///
/// </summary>
/// <short></short>
/// <category>Voip</category>
/// <returns></returns>
/// <exception cref="SecurityException"></exception>
[Read(@"voip/numbers/settings")]
public object GetVoipSettings()
{
if (!_crmSecurity.IsAdmin) throw _crmSecurity.CreateSecurityException();
var dao = _daoFactory.GetVoipDao();
var number = dao.GetNumbers().FirstOrDefault(r => r.Settings.Queue != null);
if (number != null)
{
return new { queue = number.Settings.Queue, pause = number.Settings.Pause };
}
var files = StorageFactory.GetStorage("", "crm").ListFiles("voip", "default/" + AudioType.Queue.ToString().ToLower(), "*.*", true);
var file = files.FirstOrDefault();
return new { queue = new Queue(null, "Default", 5, file != null ? CommonLinkUtility.GetFullAbsolutePath(file.ToString()) : "", 5), pause = false };
}
/// <summary>
///
/// </summary>
/// <short></short>
/// <category>Voip</category>
/// <returns></returns>
/// <exception cref="SecurityException"></exception>
[Read(@"voip/uploads")]
public IEnumerable<VoipUpload> GetUploadedFilesUri()
{
if (!_crmSecurity.IsAdmin) throw _crmSecurity.CreateSecurityException();
var result = new List<VoipUpload>();
foreach (var audioType in Enum.GetNames(typeof(AudioType)))
{
var type = (AudioType)Enum.Parse(typeof(AudioType), audioType);
var path = audioType.ToLower();
var store = Global.GetStore();
var filePaths = store.ListFilesRelative("voip", path, "*", true);
result.AddRange(
filePaths.Select(filePath =>
GetVoipUpload(store.GetUri("voip", Path.Combine(path, filePath)), Path.GetFileName(filePath), type)));
path = "default/" + audioType.ToLower();
store = StorageFactory.GetStorage("", "crm");
filePaths = store.ListFilesRelative("voip", path, "*.*", true);
result.AddRange(
filePaths.Select(filePath =>
GetVoipUpload(store.GetUri("voip", Path.Combine(path, filePath)), Path.GetFileName(filePath), type, true)));
}
return result;
}
private VoipUpload GetVoipUpload(Uri link, string fileName, AudioType audioType, bool isDefault = false)
{
return new VoipUpload
{
Path = CommonLinkUtility.GetFullAbsolutePath(link.ToString()),
Name = fileName,
AudioType = audioType,
IsDefault = isDefault
};
}
/// <summary>
///
/// </summary>
/// <short></short>
/// <category>Voip</category>
/// <returns></returns>
/// <exception cref="SecurityException"></exception>
/// <exception cref="ItemNotFoundException"></exception>
[Delete(@"voip/uploads")]
public VoipUpload DeleteUploadedFile(AudioType audioType, string fileName)
{
if (!_crmSecurity.IsAdmin) throw _crmSecurity.CreateSecurityException();
var store = Global.GetStore();
var path = Path.Combine(audioType.ToString().ToLower(), fileName);
var result = new VoipUpload
{
AudioType = audioType,
Name = fileName,
Path = CommonLinkUtility.GetFullAbsolutePath(store.GetUri(path).ToString())
};
if (!store.IsFile("voip", path)) throw new ItemNotFoundException();
store.Delete("voip", path);
var dao = _daoFactory.GetVoipDao();
var numbers = dao.GetNumbers();
var defAudio = StorageFactory.GetStorage("", "crm").ListFiles("voip", "default/" + audioType.ToString().ToLower(), "*.*", true).FirstOrDefault();
if (defAudio == null) return result;
foreach (var number in numbers)
{
switch (audioType)
{
case AudioType.Greeting:
if (number.Settings.GreetingAudio == result.Path)
{
number.Settings.GreetingAudio = CommonLinkUtility.GetFullAbsolutePath(defAudio.ToString());
}
break;
case AudioType.HoldUp:
if (number.Settings.HoldAudio == result.Path)
{
number.Settings.HoldAudio = CommonLinkUtility.GetFullAbsolutePath(defAudio.ToString());
}
break;
case AudioType.Queue:
var queue = number.Settings.Queue;
if (queue != null && queue.WaitUrl == result.Path)
{
queue.WaitUrl = CommonLinkUtility.GetFullAbsolutePath(defAudio.ToString());
}
break;
case AudioType.VoiceMail:
if (number.Settings.VoiceMail == result.Path)
{
number.Settings.VoiceMail = CommonLinkUtility.GetFullAbsolutePath(defAudio.ToString());
}
break;
}
dao.SaveOrUpdateNumber(number);
}
return result;
}
/// <summary>
///
/// </summary>
/// <short></short>
/// <category>Voip</category>
/// <returns></returns>
/// <exception cref="SecurityException"></exception>
[Read(@"voip/numbers/{numberId:regex(\w+)}/oper")]
public IEnumerable<Guid> GetOperators(string numberId)
{
return _daoFactory.GetVoipDao().GetNumber(numberId).Settings.Operators.Select(r => r.Id);
}
/// <summary>
///
/// </summary>
/// <short></short>
/// <category>Voip</category>
/// <returns></returns>
/// <exception cref="SecurityException"></exception>
/// <exception cref="ArgumentException"></exception>
[Update(@"voip/numbers/{numberId:regex(\w+)}/oper")]
public IEnumerable<Agent> AddOperators(string numberId, IEnumerable<Guid> operators)
{
if (!_crmSecurity.IsAdmin) throw _crmSecurity.CreateSecurityException();
if (_daoFactory.GetVoipDao().GetNumbers().SelectMany(r => r.Settings.Operators).Any(r => operators.Contains(r.Id)))
{
throw new ArgumentException("Duplicate", "operators");
}
var dao = _daoFactory.GetVoipDao();
var phone = dao.GetNumber(numberId);
var lastOper = phone.Settings.Operators.LastOrDefault();
var startOperId = lastOper != null ? Convert.ToInt32(lastOper.PostFix) + 1 : 100;
var addedOperators = operators.Select(o => new Agent(o, AnswerType.Client, phone, (startOperId++).ToString(CultureInfo.InvariantCulture))).ToList();
phone.Settings.Operators.AddRange(addedOperators);
dao.SaveOrUpdateNumber(phone);
return addedOperators;
}
/// <summary>
///
/// </summary>
/// <short></short>
/// <category>Voip</category>
/// <returns></returns>
/// <exception cref="SecurityException"></exception>
[Delete(@"voip/numbers/{numberId:regex(\w+)}/oper")]
public Guid DeleteOperator(string numberId, Guid oper)
{
if (!_crmSecurity.IsAdmin) throw _crmSecurity.CreateSecurityException();
var dao = _daoFactory.GetVoipDao();
var phone = dao.GetNumber(numberId);
var startOperId = 100;
phone.Settings.Operators.RemoveAll(r => r.Id == oper);
phone.Settings.Operators.ToList()
.ForEach(r =>
{
r.PhoneNumber = phone.Number;
r.PostFix = startOperId.ToString(CultureInfo.InvariantCulture);
startOperId++;
});
dao.SaveOrUpdateNumber(phone);
return oper;
}
/// <summary>
///
/// </summary>
/// <short></short>
/// <category>Voip</category>
/// <returns></returns>
/// <exception cref="SecurityException"></exception>
[Update(@"voip/opers/{operatorId}")]
public Agent UpdateOperator(Guid operatorId, AgentStatus? status, bool? allowOutgoingCalls, bool? record, AnswerType? answerType, string redirectToNumber)
{
if (!_crmSecurity.IsAdmin && !operatorId.Equals(SecurityContext.CurrentAccount.ID)) throw _crmSecurity.CreateSecurityException();
var dao = _daoFactory.GetVoipDao();
var phone = dao.GetNumbers().FirstOrDefault(r => r.Settings.Operators.Exists(a => a.Id == operatorId)).NotFoundIfNull();
var oper = phone.Settings.Operators.Find(r => r.Id == operatorId);
if (status.HasValue)
{
oper.Status = status.Value;
}
if (allowOutgoingCalls.HasValue)
{
oper.AllowOutgoingCalls = phone.Settings.AllowOutgoingCalls && allowOutgoingCalls.Value;
}
if (record.HasValue)
{
oper.Record = phone.Settings.Record && record.Value;
}
if (answerType.HasValue)
{
oper.Answer = answerType.Value;
}
if (!string.IsNullOrEmpty(redirectToNumber))
{
oper.RedirectToNumber = redirectToNumber;
}
dao.SaveOrUpdateNumber(phone);
if (allowOutgoingCalls.HasValue)
{
new SignalRHelper(phone.Number, SignalrServiceClient).Reload(operatorId.ToString());
}
return oper;
}
/// <summary>
///
/// </summary>
/// <short></short>
/// <category>Voip</category>
/// <returns></returns>
/// <exception cref="SecurityException"></exception>
[Create(@"voip/call")]
public VoipCallDto MakeCall(string to, string contactId)
{
var number = _daoFactory.GetVoipDao().GetCurrentNumber().NotFoundIfNull();
if (!number.Settings.Caller.AllowOutgoingCalls) throw new SecurityException(CRMErrorsResource.AccessDenied);
var contactPhone = to.TrimStart('+');
ContactDto contact;
if (String.IsNullOrEmpty(contactId))
{
var ids = _daoFactory.GetContactDao().GetContactIDsByContactInfo(ContactInfoType.Phone, contactPhone, null, null);
contact = _daoFactory.GetContactDao().GetContacts(ids.ToArray()).ConvertAll(x => _mapper.Map<ContactDto>(x)).FirstOrDefault();
}
else
{
contact = _mapper.Map<ContactDto>(_daoFactory.GetContactDao().GetByID(Convert.ToInt32(contactId)));
}
if (contact == null)
{
contact = _mapper.Map<ContactDto>(VoipEngine.CreateContact(contactPhone));
}
contact = GetContactWithFotos(contact);
var call = number.Call(to, contact.Id.ToString(CultureInfo.InvariantCulture));
return VoipCallDtoHelper.Get(call, contact);
}
/// <summary>
///
/// </summary>
/// <short></short>
/// <category>Voip</category>
/// <returns></returns>
[Create(@"voip/call/{callId:regex(\w+)}/answer")]
public VoipCallDto AnswerCall(string callId)
{
var dao = _daoFactory.GetVoipDao();
var call = dao.GetCall(callId).NotFoundIfNull();
var number = dao.GetCurrentNumber().NotFoundIfNull();
number.AnswerQueueCall(call.Id);
return VoipCallDtoHelper.Get(call);
}
/// <summary>
///
/// </summary>
/// <short></short>
/// <category>Voip</category>
/// <returns></returns>
[Create(@"voip/call/{callId:regex(\w+)}/reject")]
public VoipCallDto RejectCall(string callId)
{
var dao = _daoFactory.GetVoipDao();
var call = dao.GetCall(callId).NotFoundIfNull();
var number = dao.GetCurrentNumber().NotFoundIfNull();
number.RejectQueueCall(call.Id);
return VoipCallDtoHelper.Get(call);
}
/// <summary>
///
/// </summary>
/// <short></short>
/// <category>Voip</category>
/// <returns></returns>
[Create(@"voip/call/{callId:regex(\w+)}/redirect")]
public VoipCallDto ReditectCall(string callId, string to)
{
var dao = _daoFactory.GetVoipDao();
var call = dao.GetCall(callId).NotFoundIfNull();
var number = dao.GetCurrentNumber().NotFoundIfNull();
if (call.ContactId != 0)
{
var contact = _daoFactory.GetContactDao().GetByID(call.ContactId);
var managers = _crmSecurity.GetAccessSubjectGuidsTo(contact);
if (!managers.Contains(Guid.Parse(to)))
{
managers.Add(Guid.Parse(to));
_crmSecurity.SetAccessTo(contact, managers);
}
}
number.RedirectCall(call.Id, to);
return VoipCallDtoHelper.Get(call);
}
/// <summary>
///
/// </summary>
/// <short></short>
/// <category>Voip</category>
/// <returns></returns>
[Create(@"voip/call/{callId:regex(\w+)}")]
public VoipCallDto SaveCall(string callId, string from, string to, Guid answeredBy, VoipCallStatus? status, string contactId, decimal? price)
{
var dao = _daoFactory.GetVoipDao();
var call = dao.GetCall(callId) ?? new VoipCall();
call.Id = callId;
call.From = Update.IfNotEmptyAndNotEquals(call.From, from);
call.To = Update.IfNotEmptyAndNotEquals(call.To, to);
call.AnsweredBy = Update.IfNotEmptyAndNotEquals(call.AnsweredBy, answeredBy);
try
{
if (call.ContactId == 0)
{
var contactPhone = call.Status == VoipCallStatus.Incoming || call.Status == VoipCallStatus.Answered ? call.From : call.To;
if (!string.IsNullOrEmpty(contactId))
{
call.ContactId = Convert.ToInt32(contactId);
}
else
{
VoipEngine.GetContact(call);
}
if (call.ContactId == 0)
{
contactPhone = contactPhone.TrimStart('+');
var peopleInst = new Person
{
FirstName = contactPhone,
LastName = TenantUtil.DateTimeFromUtc(DateTime.UtcNow).ToString("yyyy-MM-dd hh:mm"),
ShareType = ShareType.None
};
peopleInst.ID = _daoFactory.GetContactDao().SaveContact(peopleInst);
_crmSecurity.SetAccessTo(peopleInst, new List<Guid> { SecurityContext.CurrentAccount.ID });
var person = (PersonDto)_mapper.Map<ContactDto>(peopleInst);
_daoFactory.GetContactInfoDao().Save(new ContactInfo { ContactID = person.Id, IsPrimary = true, InfoType = ContactInfoType.Phone, Data = contactPhone });
call.ContactId = person.Id;
}
}
}
catch (Exception)
{
}
if (status.HasValue)
{
call.Status = status.Value;
}
if (call.Price == 0 && price.HasValue)
{
call.Price = price.Value;
}
call = dao.SaveOrUpdateCall(call);
if (call.ContactId == 0) return VoipCallDtoHelper.Get(call);
try
{
var contact = _mapper.Map<ContactDto>(_daoFactory.GetContactDao().GetByID(call.ContactId));
contact = GetContactWithFotos(contact);
return VoipCallDtoHelper.Get(call, contact);
}
catch (Exception)
{
return VoipCallDtoHelper.Get(call);
}
}
/// <summary>
///
/// </summary>
/// <short></short>
/// <category>Voip</category>
/// <returns></returns>
[Create(@"voip/price/{callId:regex(\w+)}")]
public void SavePrice(string callId)
{
VoipEngine.SaveAdditionalInfo(callId);
}
/// <summary>
///
/// </summary>
/// <short></short>
/// <category>Voip</category>
/// <returns></returns>
[Read(@"voip/call")]
public IEnumerable<VoipCallDto> GetCalls(string callType, ApiDateTime from, ApiDateTime to, Guid? agent, int? client, int? contactID)
{
var voipDao = _daoFactory.GetVoipDao();
var filter = new VoipCallFilter
{
Type = callType,
FromDate = from != null ? from.UtcTime : (DateTime?)null,
ToDate = to != null ? to.UtcTime.AddDays(1).AddMilliseconds(-1) : (DateTime?)null,
Agent = agent,
Client = client,
ContactID = contactID,
SortBy = ApiContext.SortBy,
SortOrder = !ApiContext.SortDescending,
SearchText = ApiContext.FilterValue,
Offset = ApiContext.StartIndex,
Max = ApiContext.Count,
};
ApiContext.SetDataPaginated();
ApiContext.SetDataFiltered();
ApiContext.SetDataSorted();
ApiContext.TotalCount = voipDao.GetCallsCount(filter);
var defaultSmallPhoto = ContactPhotoManager.GetSmallSizePhoto(-1, false);
var calls = voipDao.GetCalls(filter).Select(
r =>
{
ContactDto contact;
if (r.ContactId != 0)
{
contact = r.ContactIsCompany
? (ContactDto)new CompanyDto() { DisplayName = r.ContactTitle, Id = r.ContactId }
: new PersonDto()
{
DisplayName = r.ContactTitle,
Id = r.ContactId
};
contact.SmallFotoUrl = ContactPhotoManager.GetSmallSizePhoto(contact.Id, contact.IsCompany);
}
else
{
contact = new PersonDto() { SmallFotoUrl = defaultSmallPhoto, Id = -1 };
}
return VoipCallDtoHelper.Get(r, contact);
}).ToList();
return calls;
}
/// <summary>
///
/// </summary>
/// <short></short>
/// <category>Voip</category>
/// <returns></returns>
[Read(@"voip/call/missed")]
public IEnumerable<VoipCallDto> GetMissedCalls()
{
var voipDao = _daoFactory.GetVoipDao();
var defaultSmallPhoto = ContactPhotoManager.GetSmallSizePhoto(-1, false);
var calls = voipDao.GetMissedCalls(SecurityContext.CurrentAccount.ID, 10, DateTime.UtcNow.AddDays(-7)).Select(
r =>
{
ContactDto contact;
if (r.ContactId != 0)
{
contact = r.ContactIsCompany
? (ContactDto)new CompanyDto() { DisplayName = r.ContactTitle, Id = r.ContactId }
: new PersonDto() { DisplayName = r.ContactTitle, Id = r.ContactId };
contact.SmallFotoUrl = ContactPhotoManager.GetSmallSizePhoto(contact.Id, contact.IsCompany);
}
else
{
contact = new PersonDto() { SmallFotoUrl = defaultSmallPhoto, Id = -1 };
}
return VoipCallDtoHelper.Get(r, contact);
}).ToList();
ApiContext.SetDataPaginated();
ApiContext.SetDataFiltered();
ApiContext.SetDataSorted();
ApiContext.TotalCount = calls.Count;
return calls;
}
/// <summary>
///
/// </summary>
/// <short></short>
/// <category>Voip</category>
/// <returns></returns>
[Read(@"voip/call/{callId:regex(\w+)}")]
public VoipCallDto GetCall(string callId)
{
var call = _daoFactory.GetVoipDao().GetCall(callId);
VoipEngine.GetContact(call);
if (call.ContactId == 0) return VoipCallDtoHelper.Get(call);
var contact = _mapper.Map<ContactDto>(_daoFactory.GetContactDao().GetByID(call.ContactId));
contact = GetContactWithFotos(contact);
return VoipCallDtoHelper.Get(call, contact);
}
private ContactDto GetContactWithFotos(ContactDto contact)
{
contact.SmallFotoUrl = ContactPhotoManager.GetSmallSizePhoto(contact.Id, contact.IsCompany);
contact.MediumFotoUrl = ContactPhotoManager.GetMediumSizePhoto(contact.Id, contact.IsCompany);
return contact;
}
}
}