public async Task <IActionResult> New([FromBody] MetricUpdateRequest data)
        {
            if (data == null)
            {
                return(BadRequest("No data received."));
            }

            //make sure only the author or a system administrator is saving metric, and they have the author metric claim
            if (!User.HasClaim(cl => cl.Type == Identity.Claims.AuthorMetric_Key))
            {
                return(BadRequest("The current user does not have permission to author a metric."));
            }

            //TODO: validate the minimum required metadata is included

            var currentUserID = Guid.Parse(User.Claims.Where(x => x.Type == Identity.Claims.UserID_Key).Select(x => x.Value).FirstOrDefault());

            var metric = new Model.Metric {
                AuthorID        = currentUserID,
                Description     = data.Description,
                Justification   = data.Justification,
                ExpectedResults = data.ExpectedResults,
                ModifiedOn      = DateTime.UtcNow,
                ResultsTypeID   = data.ResultsTypeID,
                ServiceDeskUrl  = data.ServiceDeskUrl ?? string.Empty,
                Title           = data.Title
            };

            _db.Metrics.Add(metric);

            metric.Statuses.Add(new Model.MetricStatusItem {
                MetricID = metric.ID, MetricStatusID = Model.MetricStatus.DraftID, UserID = currentUserID
            });

            foreach (var domainID in data.Domains)
            {
                metric.AddDomains(domainID);
            }

            foreach (var frameworkCategoryID in data.FrameworkCategories)
            {
                metric.AddFrameworkCategories(frameworkCategoryID);
            }

            await _db.SaveChangesAsync();

            return(await Get(metric.ID));
        }
        public async Task <IActionResult> Update([FromBody] MetricUpdateRequest data)
        {
            if (data == null)
            {
                return(BadRequest("No data received."));
            }

            var metric = await _db.Metrics
                         .Include(m => m.Domains)
                         .Include(m => m.FrameworkCategories)
                         .Where(m => m.ID == data.ID).FirstOrDefaultAsync();

            if (metric == null)
            {
                return(NotFound());
            }

            //make sure only the author or a system administrator is saving metric, and they have the author metric claim
            if (!User.HasClaim(cl => cl.Type == Identity.Claims.AuthorMetric_Key))
            {
                return(BadRequest("The current user does not have permission to author a metric."));
            }

            var currentUserID = Guid.Parse(User.Claims.Where(x => x.Type == Identity.Claims.UserID_Key).Select(x => x.Value).FirstOrDefault());

            if (metric.AuthorID != currentUserID && !User.HasClaim(cl => cl.Type == Identity.Claims.SystemAdministrator_Key))
            {
                return(BadRequest("The current user is not the author of the metric and does not have permission to edit the metric."));
            }

            var currentStatus = await _db.MetricStatusItems.Where(si => si.MetricID == metric.ID).OrderByDescending(si => si.CreateOn).Select(si => si.MetricStatus).FirstOrDefaultAsync();

            if (currentStatus.AllowEdit == false)
            {
                return(BadRequest("The current status of the metric does not allow for edit."));
            }

            //TODO: validate the minimum required metadata is included

            //update the metric
            metric.Description     = data.Description;
            metric.Justification   = data.Justification;
            metric.ExpectedResults = data.ExpectedResults;
            metric.ModifiedOn      = DateTime.UtcNow;
            metric.ResultsTypeID   = data.ResultsTypeID;
            metric.ServiceDeskUrl  = data.ServiceDeskUrl;
            metric.Title           = data.Title;

            foreach (var domainID in data.Domains.Except(metric.Domains.Select(d => d.DomainID)))
            {
                metric.AddDomains(domainID);
            }

            foreach (var domain in metric.Domains.Where(d => !data.Domains.Contains(d.DomainID)).ToArray())
            {
                metric.Domains.Remove(domain);
            }

            foreach (var frameworkCategoryID in data.FrameworkCategories.Except(metric.FrameworkCategories.Select(d => d.DataQualityFrameworkCategoryID)))
            {
                metric.AddFrameworkCategories(frameworkCategoryID);
            }

            foreach (var category in metric.FrameworkCategories.Where(c => !data.FrameworkCategories.Contains(c.DataQualityFrameworkCategoryID)).ToArray())
            {
                metric.FrameworkCategories.Remove(category);
            }

            await _db.SaveChangesAsync();

            return(await Get(data.ID));
        }