/// <summary>
        /// Maps a AgileCrmDealEntity onto a DealEntityBase.
        /// </summary>
        /// <param name="agileCrmDealModel">The AgileCRM deal model.</param>
        /// <returns>
        ///   <see cref="AgileCrmDealEntity" />.
        /// </returns>
        public static AgileCrmDealEntity ToDealEntityBase(this AgileCrmDealRequest agileCrmDealModel)
        {
            var agileCrmCustomDataEntities = new List <AgileCrmCustomDataEntity>();

            foreach (var keyValuePair in agileCrmDealModel.CustomFields)
            {
                agileCrmCustomDataEntities.Add(
                    new AgileCrmCustomDataEntity
                {
                    Name  = keyValuePair.Key,
                    Value = keyValuePair.Value
                });
            }

            var agileCrmServerDealEntity = new AgileCrmDealEntity
            {
                // Id = (set by calling method if required).
                // TrackId = (set by calling method if required).
                // ContactId = (set by calling method if required).
                Name        = agileCrmDealModel.Name,
                CloseDate   = agileCrmDealModel.CloseDate.ToEpoch(),
                Milestone   = agileCrmDealModel.Milestone,
                Probability = agileCrmDealModel.Probability,
                Value       = agileCrmDealModel.Value,
                CustomData  = agileCrmCustomDataEntities
            };

            return(agileCrmServerDealEntity);
        }
        /// <inheritdoc />
        public async Task UpdateAsync(long dealId, AgileCrmDealRequest agileCrmDealModel)
        {
            const string MethodName = nameof(this.UpdateAsync);

            this.logger.LogMethodStart(ClassName, MethodName);

            try
            {
                // Validate argument object
                agileCrmDealModel.ValidateModel();

                // Serialize object to JSON
                var dealEntityBase = agileCrmDealModel.ToDealEntityBase();

                dealEntityBase.Id = dealId;

                var stringContent = dealEntityBase.ToStringContent();

                // Send JSON to server
                const string Uri = "opportunity/partial-update";

                var httpResponseMessage = await this.httpClient.PutAsync(Uri, stringContent).ConfigureAwait(false);

                // Analyze server response for errors
                httpResponseMessage.EnsureSuccessStatusCode();
            }
            catch (Exception exception)
            {
                this.logger.LogException(ClassName, MethodName, exception);
                throw;
            }

            this.logger.LogUpdated(ServiceType.Deal, dealId);
            this.logger.LogMethodEnd(ClassName, MethodName);
        }
        /// <inheritdoc />
        public async Task CreateAsync(string emailAddress, AgileCrmDealRequest agileCrmDealModel)
        {
            const string MethodName = nameof(this.CreateAsync);

            this.logger.LogMethodStart(ClassName, MethodName);

            var dealId = default(long);

            try
            {
                // Validate argument object
                agileCrmDealModel.ValidateModel();

                // Serialize object to JSON
                var dealEntityBase = agileCrmDealModel.ToDealEntityBase();

                var stringContent = dealEntityBase.ToStringContent();

                // Send JSON to server
                var uri = $"opportunity/email/{emailAddress}";

                var httpResponseMessage = await this.httpClient.PostAsync(uri, stringContent).ConfigureAwait(false);

                // Analyze server response for errors
                httpResponseMessage.EnsureSuccessStatusCode();

                // Retrieve identifier for logging
                var httpContentAsString = await httpResponseMessage.Content.ReadAsStringAsync().ConfigureAwait(false);

                dealId = httpContentAsString.DeserializeJson(new { id = default(long) }).id;
            }
            catch (Exception exception)
            {
                this.logger.LogException(ClassName, MethodName, exception);
                throw;
            }

            this.logger.LogCreated(ServiceType.Deal, dealId);
            this.logger.LogMethodEnd(ClassName, MethodName);
        }