public VoipCallWrapper 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);

            if (call.ContactId == 0)
            {
                var contactPhone = call.Status == VoipCallStatus.Incoming ? from : to;
                if (!string.IsNullOrEmpty(contactId))
                {
                    call.ContactId = Convert.ToInt32(contactId);
                }
                else if (status.HasValue && (status.Value == VoipCallStatus.Incoming || status.Value == VoipCallStatus.Outcoming))
                {
                    call.ContactId = DaoFactory.GetContactDao().GetContactIDsByContactInfo(ContactInfoType.Phone, contactPhone.TrimStart('+'), null, null).FirstOrDefault();
                }

                if (call.ContactId == 0)
                {
                    var person = CreatePerson(contactPhone, TenantUtil.DateTimeFromUtc(DateTime.UtcNow).ToString("yyyy-MM-dd hh:mm"), null, 0, null, ShareType.None, new List <Guid> {
                        SecurityContext.CurrentAccount.ID
                    }, null, null);
                    DaoFactory.GetContactInfoDao().Save(new ContactInfo {
                        ContactID = person.ID, IsPrimary = true, InfoType = ContactInfoType.Phone, Data = contactPhone
                    });
                    call.ContactId = person.ID;
                }
            }

            if (status.HasValue)
            {
                call.Status = status.Value;
            }

            if (call.Price == 0 && price.HasValue)
            {
                call.Price = price.Value;
                VoipPaymentSettings.Increment((int)(price.Value * 1000));
            }

            call = dao.SaveOrUpdateCall(call);

            if (call.ContactId == 0)
            {
                return(new VoipCallWrapper(call));
            }

            var contact = GetContactByID(call.ContactId);

            contact = GetContactWithFotos(contact);

            return(new VoipCallWrapper(call, contact));
        }
        public VoipCallHistory SaveCallHistory(string callId, string parentCallId, Guid?answeredBy, string recordUrl, int recordDuration, decimal?price,
                                               ApiDateTime queueDate = null, ApiDateTime answerDate = null, ApiDateTime endDialDate = null)
        {
            var dao        = DaoFactory.GetVoipDao();
            var parentCall = dao.GetCall(parentCallId).NotFoundIfNull();

            var listItemDao = DaoFactory.GetListItemDao();
            var call        = dao.GetCallHistoryById(parentCallId, callId);

            if (call == null)
            {
                if (parentCallId != callId)
                {
                    call = dao.GetCallHistoryById(parentCallId, parentCallId);
                }

                if (call == null)
                {
                    call = new VoipCallHistory {
                        ID = callId
                    };
                }
                else
                {
                    call.ID = callId;
                    dao.UpdateCallHistoryId(call);
                }
            }

            call.ParentID = parentCallId;

            if (answeredBy.HasValue)
            {
                call.AnsweredBy = answeredBy.Value;
            }

            call.QueueDate  = Update.IfNotEmptyAndNotEquals(call.QueueDate, queueDate);
            call.AnswerDate = Update.IfNotEmptyAndNotEquals(call.AnswerDate, answerDate);

            if (endDialDate != null)
            {
                call.EndDialDate = endDialDate;
                var note = parentCall.Status == VoipCallStatus.Incoming ? CRMContactResource.HistoryVoipIncomingNote : CRMContactResource.HistoryVoipOutcomingNote;

                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);
                }
                AddHistoryTo(null, 0, parentCall.ContactId, string.Format(note, call.EndDialDate.Subtract(call.AnswerDate).Seconds.ToString(CultureInfo.InvariantCulture)), category.ID, (ApiDateTime)(DateTime.UtcNow), null, null);
            }

            call.RecordUrl = Update.IfNotEmptyAndNotEquals(call.RecordUrl, recordUrl);


            if (recordDuration != 0)
            {
                call.RecordDuration = recordDuration;
            }

            if (call.Price == 0 && price.HasValue)
            {
                call.Price = price.Value;
                VoipPaymentSettings.Increment((int)(price.Value * 1000));
            }

            return(dao.SaveOrUpdateCallHistory(call));
        }