/// <summary> /// Creates a new relation between two pages. /// </summary> public Relation AddRelation(Page source, RelationType type, Page target, string duration = null, Page eventPage = null) { if (!RelationHelper.IsRelationAllowed(source.Type, target.Type, type)) { throw new ArgumentException("This relation is not allowed!"); } if (eventPage != null) { if (!RelationHelper.IsRelationEventReferenceAllowed(type)) { throw new ArgumentException("This relation cannot have an event reference."); } if (eventPage.Type != PageType.Event) { throw new ArgumentException("The related event page must have Event type."); } } var rel = new Relation { Id = Guid.NewGuid(), Source = source, Destination = target, Event = eventPage, Type = type, Duration = duration, IsComplementary = false }; _db.Relations.Add(rel); var invRel = new Relation { Id = Guid.NewGuid(), Source = target, Destination = source, Event = eventPage, Type = RelationHelper.ComplementaryRelations[type], Duration = duration, IsComplementary = true }; _db.Relations.Add(invRel); return(rel); }
/// <summary> /// Checks if the create/update request contains valid data. /// </summary> private async Task ValidateRequestAsync(RelationEditorVM vm, bool isNew) { var val = new Validator(); vm.SourceIds = vm.SourceIds ?? new Guid[0]; var pageIds = vm.SourceIds .Concat(new [] { vm.DestinationId ?? Guid.Empty, vm.EventId ?? Guid.Empty }) .ToList(); var pages = await _db.Pages .Where(x => pageIds.Contains(x.Id)) .ToDictionaryAsync(x => x.Id, x => x.Type); var sourceTypes = vm.SourceIds.Select(x => pages.TryGetNullableValue(x)).ToList(); var destType = pages.TryGetNullableValue(vm.DestinationId ?? Guid.Empty); var eventType = pages.TryGetNullableValue(vm.EventId ?? Guid.Empty); if (vm.SourceIds == null || vm.SourceIds.Length == 0) { val.Add(nameof(vm.SourceIds), "Выберите страницу"); } else if (isNew == false && vm.SourceIds.Length > 1) { val.Add(nameof(vm.SourceIds), "При редактировании может быть указана только одна страница"); } else if (sourceTypes.Any(x => x == null)) { val.Add(nameof(vm.SourceIds), "Страница не найдена"); } if (vm.DestinationId == null) { val.Add(nameof(vm.DestinationId), "Выберите страницу"); } else if (destType == null) { val.Add(nameof(vm.DestinationId), "Страница не найдена"); } if (destType != null && sourceTypes.Any(x => x != null && !RelationHelper.IsRelationAllowed(x.Value, destType.Value, vm.Type))) { val.Add(nameof(vm.Type), "Тип связи недопустимм для данных страниц"); } if (vm.EventId != null) { if (eventType == null) { val.Add(nameof(vm.EventId), "Страница не найдена"); } else if (eventType != PageType.Event) { val.Add(nameof(vm.EventId), "Требуется страница события"); } else if (!RelationHelper.IsRelationEventReferenceAllowed(vm.Type)) { val.Add(nameof(vm.EventId), "Событие нельзя привязать к данному типу связи"); } } if (!string.IsNullOrEmpty(vm.DurationStart) || !string.IsNullOrEmpty(vm.DurationEnd)) { if (!RelationHelper.IsRelationDurationAllowed(vm.Type)) { val.Add(nameof(vm.DurationStart), "Дату нельзя указать для данного типа связи"); } else { var from = FuzzyDate.TryParse(vm.DurationStart); var to = FuzzyDate.TryParse(vm.DurationEnd); if (from > to) { val.Add(nameof(vm.DurationStart), "Дата начала не может быть больше даты конца"); } else if (FuzzyRange.TryParse(FuzzyRange.TryCombine(vm.DurationStart, vm.DurationEnd)) == null) { val.Add(nameof(vm.DurationStart), "Введите дату в корректном формате"); } } } var existingRelation = await _db.Relations .AnyAsync(x => vm.SourceIds.Contains(x.SourceId) && x.DestinationId == vm.DestinationId && x.Type == vm.Type && x.Id != vm.Id); if (existingRelation) { val.Add(nameof(vm.DestinationId), "Такая связь уже существует!"); } val.ThrowIfInvalid(); }