private async Task <DeleteResult> SoftDelete
            (DeleteCommand <GeoTask> command, GeoTask entity, Actor currentActor)
        {
            var historyElement = new GeoTaskHistory
            {
                ChangedAt   = DateTime.UtcNow,
                Description = command.MessageDescription,
                Title       = command.MessageTitle,
                ChangedBy   = currentActor,
            };

            historyElement.Operations.Add(new Operation
            {
                OperationType = _TJsonPatchOperation.Replace,
                OldValue      = entity.IsArchived,
                NewValue      = true,
                Path          = $"/{nameof(entity.IsArchived)}"
            });
            entity.History.Add(historyElement);

            entity.IsArchived = true;

            var updateResult = await Mediator
                               .Send(new DbUpdateCommand <GeoTask>(entity))
                               .ConfigureAwait(false);

            return(updateResult.ToDeleteResult());
        }
        private GeoTaskHistory BuildNewHistoryElement(GeoTask newGeoTask,
                                                      GeoTask oldGeoTask, GeoTaskUpdateCommand command,
                                                      Actor currentActor)
        {
            var historyRecord = new GeoTaskHistory()
            {
                ChangedAt   = DateTime.UtcNow,
                ChangedBy   = currentActor,
                Description = command.MessageDescription,
                Title       = command.MessageTitle
            };

            historyRecord.Operations
            .AddRange(newGeoTask.ToHistoryOperations(oldGeoTask));
            return(historyRecord);
        }
        public static ApiGeoTaskHistory ToApiGeoTaskHistory
            (this GeoTaskHistory from)
        {
            if (from is null)
            {
                return(null);
            }

            return(new ApiGeoTaskHistory
            {
                Description = from.Description,
                Id = from.Id,
                Title = from.Title,
                CreatedAt = from.ChangedAt,
                CreatedBy = from.ChangedBy.ToApiActor(),
            });
        }
        public async Task <CreateResult> Handle(GeoTaskCreateCommand command,
                                                CancellationToken cancellationToken)
        {
            if (command is null)
            {
                Logger.LogWarning(AppLogEvent.HandleArgumentError,
                                  "Handle create task got empty command");
                return(ErrorResult("Empty Geo Task Create command"));
            }

            var validator        = new GeoTaskCreateCommandValidator();
            var validationResult = await validator
                                   .ValidateAsync(command)
                                   .ConfigureAwait(false);

            if (!validationResult.IsValid)
            {
                Logger.LogWarning(AppLogEvent.RequestValidationError,
                                  "Validation command error. Command = {command}. " +
                                  "Error = {Error}", command.ToDictionary(),
                                  validationResult.Errors);
                return(ErrorResult
                           (validationResult.Errors.Select(x => x.ErrorMessage)));
            }

            try
            {
                var geoTask = new GeoTask()
                {
                    CreatedAt       = DateTime.UtcNow,
                    Description     = command.Description,
                    StatusChangedAt = DateTime.UtcNow,
                    IsArchived      = command.IsArchived,
                    PlanFinishAt    = command.PlanFinishAt,
                    PlanStartAt     = command.PlanStartAt,
                    Status          = GeoTaskStatus.New,
                    Title           = command.Title,
                };

                // Load from repository all mentioned actors
                var allActors = await GetActors(
                    command.AssistentActorsIds
                    .Concat(command.ObserverActorsIds)
                    .Append(command.ResponsibleActorId)
                    ).ConfigureAwait(false);

                // Add to the new entity only exist in the repository actors
                geoTask.AssistentActors.AddRange(
                    command.AssistentActorsIds
                    .Select(x => allActors
                            .FirstOrDefault(a => a.Id == x))
                    .Where(a => a != null));
                geoTask.ObserverActors.AddRange(
                    command.ObserverActorsIds
                    .Select(x => allActors
                            .FirstOrDefault(a => a.Id == x))
                    .Where(a => a != null));
                geoTask.ResponsibleActor = allActors
                                           .FirstOrDefault(a => a.Id == command.ResponsibleActorId);

                // Check that Geo Ids exist in repository
                geoTask.GeosIds.AddRange(await GetGeosIds(command.GeosIds)
                                         .ConfigureAwait(false));

                // Get Actor for current user by user name
                var creatorResponse = await Mediator
                                      .Send(new DbGetActorByNameRequest
                                            (command.CurrentPrincipal?.Identity?.Name))
                                      .ConfigureAwait(false);

                Actor createdBy = null;
                if (creatorResponse.Success)
                {
                    createdBy = creatorResponse.Entity;
                }

                geoTask.CreatedBy = createdBy;

                Project project = await GetProject(command.ProjectId)
                                  .ConfigureAwait(false);

                geoTask.ProjectId = project?.Id;

                var historyRec = new GeoTaskHistory
                {
                    ChangedAt = DateTime.UtcNow,
                    ChangedBy = createdBy,
                };
                historyRec.Operations.Add(new Operation
                {
                    OperationType = addOperation,
                    Path          = "/",
                    NewValue      = geoTask.ToDictionary()
                });
                geoTask.History.Add(historyRec);

                var validatorBeforeSave        = new GeoTaskBeforeSaveValidator();
                var validationBeforeSaveResult = await validatorBeforeSave
                                                 .ValidateAsync(geoTask)
                                                 .ConfigureAwait(false);

                if (!validationBeforeSaveResult.IsValid)
                {
                    Logger.LogWarning(AppLogEvent.RequestNotValid,
                                      "GeoTask validation error. Entity={Entity}. " +
                                      "Error={Error}.", geoTask.ToDictionary(),
                                      validationBeforeSaveResult.Errors);
                    return(ErrorResult(validationBeforeSaveResult.Errors
                                       .Select(x => x.ErrorMessage)));
                }

                var checkPermissionResult = await CheckPermission
                                                (geoTask, createdBy, project)
                                            .ConfigureAwait(false);

                if (!checkPermissionResult.Success)
                {
                    Logger.LogWarning(AppLogEvent.SecurityNotPassed,
                                      "GeoTask check create permission error. " +
                                      "Entity={Entity}. CurrentActor={CurrentActor}. " +
                                      "Project={Project}. Error={Error}.",
                                      geoTask.ToDictionary(), createdBy?.ToDictionary(),
                                      project?.ToDictionary(), checkPermissionResult.Errors);
                    return(checkPermissionResult);
                }

                return(await Mediator
                       .Send(new DbCreateCommand <GeoTask>(geoTask))
                       .ConfigureAwait(false));
            }
            catch (Exception e)
            {
                Logger.LogError(AppLogEvent.HandleErrorResponse, e,
                                "Call repository exception");
                return(ErrorResult("Not found"));
            }
        }