public async Task <PerMessageAggregationList> GetPerMessageAggregationAsync(
            string engagementAccount,
            DateTimeOffset startTime,
            DateTimeOffset endTime,
            int count,
            TableContinuationToken continuationToken)
        {
            var historyTable = await this.GetHistoryTableAsync(engagementAccount);

            var segment = await MessageHistoryTableEntity.GetAsync(
                historyTable,
                startTime,
                endTime,
                count,
                continuationToken);

            var aggregations = await Task.WhenAll(
                segment.Select(async historyEntity =>
            {
                var countByState = await MessageDetailTableEntity.CountByStateAsync(
                    this.detailTable,
                    historyEntity.MessageId);

                return(new PerMessageAggregationList.PerMessageAggregation(
                           historyEntity,
                           countByState));
            }));

            return(new PerMessageAggregationList(
                       aggregations,
                       startTime,
                       endTime,
                       segment.ContinuationToken));
        }
        public async Task <MessageDetails> GetMessageHistoryAsync(string engagementAccount, string messageId, int count, TableContinuationToken continuationToken)
        {
            var historyTable = await this.GetHistoryTableAsync(engagementAccount);

            var record = await MessageHistoryTableEntity.GetAsync(historyTable, engagementAccount, messageId);

            if (record == null)
            {
                return(null);
            }

            var result = new MessageDetails
            {
                MessageId = record.MessageId,
                SendTime  = record.SendTime,
                Targets   = record.Targets
            };

            // Calculate success and failed count
            var tuple = await MessageDetailTableEntity.GetResultAsync(this.detailTable, engagementAccount, messageId);

            result.Succeed = tuple.Item1;
            result.Failed  = tuple.Item2;

            // Get details
            return(await MessageDetailTableEntity.ListAsync(this.detailTable, engagementAccount, messageId, count, continuationToken, result));
        }
        private async Task UpdateMessageDetailsAsync(string engagementAccount, MessageSummaryTableEntity summary, List <ReportDetail> reports)
        {
            var entities = new List <MessageDetailTableEntity>();
            var units    = summary.Units ?? 1;

            foreach (var report in reports)
            {
                // Duplicate detail record if units is not 1
                for (var i = 0; i < units; i++)
                {
                    entities.Add(new MessageDetailTableEntity(engagementAccount, summary.MessageId, report));
                }
            }

            await MessageDetailTableEntity.InsertOrMergeBatchAsync(this.detailTable, entities);
        }