예제 #1
0
        public async void TestQuerySpanEquipmentByInterestId_ShouldSucceed()
        {
            // Setup
            var specs = new TestSpecifications(_commandDispatcher, _queryDispatcher).Run();

            var walkOfInterest = new RouteNetworkInterest(Guid.NewGuid(), RouteNetworkInterestKindEnum.WalkOfInterest, new RouteNetworkElementIdList()
            {
                Guid.NewGuid(), Guid.NewGuid(), Guid.NewGuid()
            });

            var placeSpanEquipmentCommand = new PlaceSpanEquipmentInRouteNetwork(Guid.NewGuid(), TestSpecifications.Multi_Ø32_3x10, walkOfInterest);

            // Act
            var placeSpanEquipmentResult = await _commandDispatcher.HandleAsync <PlaceSpanEquipmentInRouteNetwork, Result>(placeSpanEquipmentCommand);

            var spanEquipmentQueryResult = await _queryDispatcher.HandleAsync <GetEquipmentDetails, Result <GetEquipmentDetailsResult> >(
                new GetEquipmentDetails(new InterestIdList()
            {
                walkOfInterest.Id
            })
                );

            // Assert
            placeSpanEquipmentResult.IsSuccess.Should().BeTrue();
            spanEquipmentQueryResult.IsSuccess.Should().BeTrue();

#pragma warning disable CS8602 // Dereference of a possibly null reference.
            spanEquipmentQueryResult.Value.SpanEquipment[placeSpanEquipmentCommand.SpanEquipmentId].Id.Should().Be(placeSpanEquipmentCommand.SpanEquipmentId);
#pragma warning restore CS8602 // Dereference of a possibly null reference.
        }
        private Guid PlaceConduit(Guid specificationId, RouteNetworkElementIdList walkIds)
        {
            // Register walk of interest
            var walkOfInterestId = Guid.NewGuid();
            var registerWalkOfInterestCommand       = new RegisterWalkOfInterest(walkOfInterestId, walkIds);
            var registerWalkOfInterestCommandResult = _commandDispatcher.HandleAsync <RegisterWalkOfInterest, Result <RouteNetworkInterest> >(registerWalkOfInterestCommand).Result;

            // Place conduit
            var placeSpanEquipmentCommand = new PlaceSpanEquipmentInRouteNetwork(Guid.NewGuid(), specificationId, registerWalkOfInterestCommandResult.Value);
            var placeSpanEquipmentResult  = _commandDispatcher.HandleAsync <PlaceSpanEquipmentInRouteNetwork, Result>(placeSpanEquipmentCommand).Result;

            if (placeSpanEquipmentResult.IsFailed)
            {
                throw new ApplicationException(placeSpanEquipmentResult.Errors.First().Message);
            }

            return(placeSpanEquipmentCommand.SpanEquipmentId);
        }
예제 #3
0
        public async void TestPlaceTwoSpanEquipmentWithSameId_SecondOneShouldFail()
        {
            // Setup
            var specs = new TestSpecifications(_commandDispatcher, _queryDispatcher).Run();

            var walkOfInterest = new RouteNetworkInterest(Guid.NewGuid(), RouteNetworkInterestKindEnum.WalkOfInterest, new RouteNetworkElementIdList()
            {
                Guid.NewGuid(), Guid.NewGuid(), Guid.NewGuid()
            });

            var placeSpanEquipmentCommand = new PlaceSpanEquipmentInRouteNetwork(Guid.NewGuid(), TestSpecifications.Multi_Ø32_3x10, walkOfInterest);

            // Act
            var placeSpanEquipmentResult = await _commandDispatcher.HandleAsync <PlaceSpanEquipmentInRouteNetwork, Result>(placeSpanEquipmentCommand);

            var placeSpanEquipmentResult2 = await _commandDispatcher.HandleAsync <PlaceSpanEquipmentInRouteNetwork, Result>(placeSpanEquipmentCommand);

            // Assert
            placeSpanEquipmentResult.IsSuccess.Should().BeTrue();
            placeSpanEquipmentResult2.IsSuccess.Should().BeFalse();
        }
예제 #4
0
        public async Task Place5x10Conduit_from_HH_1_to_HH_10()
        {
            // Place a 5x10 multi conduit here:
            // (HH_1) <- (S2) -> (HH_2) <- (S4) -> (CC_1) <- (S13) -> (HH_10)

            // First register the walk in the route network where we want to place the conduit
            var walkOfInterestId = Guid.NewGuid();
            var walk             = new RouteNetworkElementIdList()
            {
                TestRouteNetwork.S2, TestRouteNetwork.S4, TestRouteNetwork.S13
            };
            var registerWalkOfInterestCommand       = new RegisterWalkOfInterest(Guid.NewGuid(), new UserContext("test", Guid.Empty), walkOfInterestId, walk);
            var registerWalkOfInterestCommandResult = await _commandDispatcher.HandleAsync <RegisterWalkOfInterest, Result <RouteNetworkInterest> >(registerWalkOfInterestCommand);

            // Now place the conduit in walk
            var placeSpanEquipmentCommand = new PlaceSpanEquipmentInRouteNetwork(Guid.NewGuid(), new UserContext("test", Guid.Empty), TestConduits.Conduit_5x10_HH_1_to_HH_10, TestSpecifications.Multi_Ø40_5x10, registerWalkOfInterestCommandResult.Value);
            var placeSpanEquipmentResult  = await _commandDispatcher.HandleAsync <PlaceSpanEquipmentInRouteNetwork, Result>(placeSpanEquipmentCommand);

            // Assert
            registerWalkOfInterestCommandResult.IsSuccess.Should().BeTrue();
            placeSpanEquipmentResult.IsSuccess.Should().BeTrue();
        }
예제 #5
0
        public async Task PlaceØ40Flex_from_CC_1_to_SP_1()
        {
            // Place a Ø40 flex conduit here:
            // (CC_1) <- (S5) -> (SP_1)

            // First register the walk in the route network where we want to place the conduit
            var walkOfInterestId = Guid.NewGuid();
            var walk             = new RouteNetworkElementIdList()
            {
                TestRouteNetwork.S5
            };
            var registerWalkOfInterestCommand       = new RegisterWalkOfInterest(Guid.NewGuid(), new UserContext("test", Guid.Empty), walkOfInterestId, walk);
            var registerWalkOfInterestCommandResult = await _commandDispatcher.HandleAsync <RegisterWalkOfInterest, Result <RouteNetworkInterest> >(registerWalkOfInterestCommand);

            // Now place the conduit in walk
            var placeSpanEquipmentCommand = new PlaceSpanEquipmentInRouteNetwork(Guid.NewGuid(), new UserContext("test", Guid.Empty), Guid.NewGuid(), TestSpecifications.Flex_Ø40_Red, registerWalkOfInterestCommandResult.Value);
            var placeSpanEquipmentResult  = await _commandDispatcher.HandleAsync <PlaceSpanEquipmentInRouteNetwork, Result>(placeSpanEquipmentCommand);

            // Assert
            registerWalkOfInterestCommandResult.IsSuccess.Should().BeTrue();
            placeSpanEquipmentResult.IsSuccess.Should().BeTrue();
        }
예제 #6
0
        private void PlaceConduit(string externalId, Guid specificationId, List <Guid> segmentIds, List <Guid> additionalStructureSpecIds, string markingColor)
        {
            Guid correlationId = Guid.NewGuid();

            RouteNetworkElementIdList walkIds = new RouteNetworkElementIdList();

            walkIds.AddRange(segmentIds);

            // Register walk of interest
            var walkOfInterestId = Guid.NewGuid();
            var registerWalkOfInterestCommand = new RegisterWalkOfInterest(correlationId, new UserContext("conversion", _bentleyMultiConduitConversion), walkOfInterestId, walkIds);

            var registerWalkOfInterestCommandResult = _commandDispatcher.HandleAsync <RegisterWalkOfInterest, Result <RouteNetworkInterest> >(registerWalkOfInterestCommand).Result;

            if (registerWalkOfInterestCommandResult.IsFailed)
            {
                _logger.LogInformation("Failed to add conduit: " + externalId + " Error: " + registerWalkOfInterestCommandResult.Errors.First().Message);
                return;
            }

            // conduit name
            var nextConduitSeqStr = _eventStore.Sequences.GetNextVal("conduit").ToString();

            var conduitName = "R" + nextConduitSeqStr.PadLeft(6, '0');
            var namingInfo  = new NamingInfo(conduitName, null);

            // Place conduit
            var placeSpanEquipmentCommand = new PlaceSpanEquipmentInRouteNetwork(correlationId, new UserContext("conversion", _bentleyMultiConduitConversion), Guid.NewGuid(), specificationId, registerWalkOfInterestCommandResult.Value)
            {
                MarkingInfo = markingColor != null ? new MarkingInfo()
                {
                    MarkingColor = markingColor
                } : null,
                NamingInfo = namingInfo
            };

            var placeSpanEquipmentResult = _commandDispatcher.HandleAsync <PlaceSpanEquipmentInRouteNetwork, Result>(placeSpanEquipmentCommand).Result;

            if (placeSpanEquipmentResult.IsFailed)
            {
                _logger.LogInformation("Failed to add conduit: " + externalId + " Error: " + placeSpanEquipmentResult.Errors.First().Message);
                return;
            }

            // Place additional structures
            if (additionalStructureSpecIds.Count > 0)
            {
                var addStructure = new PlaceAdditionalStructuresInSpanEquipment(correlationId, new UserContext("conversion", _bentleyMultiConduitConversion),
                                                                                spanEquipmentId: placeSpanEquipmentCommand.SpanEquipmentId,
                                                                                structureSpecificationIds: additionalStructureSpecIds.ToArray()
                                                                                );

                var addStructureResult = _commandDispatcher.HandleAsync <PlaceAdditionalStructuresInSpanEquipment, Result>(addStructure).Result;

                if (addStructureResult.IsFailed)
                {
                    _logger.LogInformation("Failed to add additional structures to: " + externalId + " Error: " + placeSpanEquipmentResult.Errors.First().Message);
                    return;
                }
            }
        }
예제 #7
0
        public async void TestPlaceValidSpanEquipment_ShouldSucceed()
        {
            // Setup
            var specs = new TestSpecifications(_commandDispatcher, _queryDispatcher).Run();

            var walkOfInterestId = Guid.NewGuid();
            var registerWalkOfInterestCommand = new RegisterWalkOfInterest(walkOfInterestId, new RouteNetworkElementIdList()
            {
                TestRouteNetwork.S1
            });
            var registerWalkOfInterestCommandResult = _commandDispatcher.HandleAsync <RegisterWalkOfInterest, Result <RouteNetworkInterest> >(registerWalkOfInterestCommand).Result;

            var placeSpanEquipmentCommand = new PlaceSpanEquipmentInRouteNetwork(Guid.NewGuid(), TestSpecifications.Multi_Ø32_3x10, registerWalkOfInterestCommandResult.Value)
            {
                NamingInfo  = new NamingInfo("Hans", "Grethe"),
                MarkingInfo = new MarkingInfo()
                {
                    MarkingColor = "Red", MarkingText = "ABCDE"
                },
                ManufacturerId = Guid.NewGuid()
            };

            // Act
            var placeSpanEquipmentResult = await _commandDispatcher.HandleAsync <PlaceSpanEquipmentInRouteNetwork, Result>(placeSpanEquipmentCommand);

            var spanEquipmentQueryResult = await _queryDispatcher.HandleAsync <GetEquipmentDetails, Result <GetEquipmentDetailsResult> >(
                new GetEquipmentDetails(new EquipmentIdList()
            {
                placeSpanEquipmentCommand.SpanEquipmentId
            })
                );

            // Assert
            placeSpanEquipmentResult.IsSuccess.Should().BeTrue();
            spanEquipmentQueryResult.IsSuccess.Should().BeTrue();
            spanEquipmentQueryResult.Value.Should().NotBeNull();
            spanEquipmentQueryResult.Value.SpanEquipment.Should().NotBeNull();

#pragma warning disable CS8602 // Dereference of a possibly null reference.
            spanEquipmentQueryResult.Value.SpanEquipment[placeSpanEquipmentCommand.SpanEquipmentId].Id.Should().Be(placeSpanEquipmentCommand.SpanEquipmentId);
#pragma warning restore CS8602 // Dereference of a possibly null reference.
            spanEquipmentQueryResult.Value.SpanEquipment[placeSpanEquipmentCommand.SpanEquipmentId].SpecificationId.Should().Be(placeSpanEquipmentCommand.SpanEquipmentSpecificationId);
            spanEquipmentQueryResult.Value.SpanEquipment[placeSpanEquipmentCommand.SpanEquipmentId].WalkOfInterestId.Should().Be(placeSpanEquipmentCommand.Interest.Id);
            spanEquipmentQueryResult.Value.SpanEquipment[placeSpanEquipmentCommand.SpanEquipmentId].NamingInfo.Should().BeEquivalentTo(placeSpanEquipmentCommand.NamingInfo);
            spanEquipmentQueryResult.Value.SpanEquipment[placeSpanEquipmentCommand.SpanEquipmentId].MarkingInfo.Should().BeEquivalentTo(placeSpanEquipmentCommand.MarkingInfo);
            spanEquipmentQueryResult.Value.SpanEquipment[placeSpanEquipmentCommand.SpanEquipmentId].ManufacturerId.Should().Be(placeSpanEquipmentCommand.ManufacturerId);

            spanEquipmentQueryResult.Value.SpanEquipment[placeSpanEquipmentCommand.SpanEquipmentId].SpanStructures.Length.Should().Be(4);

            // Check that span segments are correctly populated
            for (int structureIndex = 0; structureIndex < spanEquipmentQueryResult.Value.SpanEquipment[placeSpanEquipmentCommand.SpanEquipmentId].SpanStructures.Length; structureIndex++)
            {
                spanEquipmentQueryResult.Value.SpanEquipment[placeSpanEquipmentCommand.SpanEquipmentId].SpanStructures[structureIndex].SpanSegments.Length.Should().Be(1);
                spanEquipmentQueryResult.Value.SpanEquipment[placeSpanEquipmentCommand.SpanEquipmentId].SpanStructures[structureIndex].SpanSegments[0].FromTerminalId.Should().BeEmpty();
                spanEquipmentQueryResult.Value.SpanEquipment[placeSpanEquipmentCommand.SpanEquipmentId].SpanStructures[structureIndex].SpanSegments[0].ToTerminalId.Should().BeEmpty();
                spanEquipmentQueryResult.Value.SpanEquipment[placeSpanEquipmentCommand.SpanEquipmentId].SpanStructures[structureIndex].SpanSegments[0].FromNodeOfInterestIndex.Should().Be(0);
                spanEquipmentQueryResult.Value.SpanEquipment[placeSpanEquipmentCommand.SpanEquipmentId].SpanStructures[structureIndex].SpanSegments[0].ToNodeOfInterestIndex.Should().Be(1);
                spanEquipmentQueryResult.Value.SpanEquipment[placeSpanEquipmentCommand.SpanEquipmentId].SpanStructures[structureIndex].SpanSegments[0].Id.Should().NotBeEmpty();
            }

            // Check if an event is published to the notification.utility-network topic having an idlist containing the span equipment id we just created
            var utilityNetworkNotifications = _externalEventProducer.GetMessagesByTopic("notification.utility-network").OfType <RouteNetworkElementContainedEquipmentUpdated>();
            var utilityNetworkUpdatedEvent  = utilityNetworkNotifications.First(n => n.IdChangeSets != null && n.IdChangeSets.Any(i => i.IdList.Any(i => i == placeSpanEquipmentCommand.SpanEquipmentId)));
            utilityNetworkUpdatedEvent.AffectedRouteNetworkElementIds.Should().Contain(TestRouteNetwork.CO_1);
            utilityNetworkUpdatedEvent.AffectedRouteNetworkElementIds.Should().Contain(TestRouteNetwork.S1);
            utilityNetworkUpdatedEvent.AffectedRouteNetworkElementIds.Should().Contain(TestRouteNetwork.HH_1);
        }
예제 #8
0
        public SpanEquipmentMutations(ICommandDispatcher commandDispatcher, IEventStore eventStore)
        {
            Description = "Span equipment mutations";

            FieldAsync <CommandResultType>(
                "placeSpanEquipmentInRouteNetwork",
                description: "Place a span equipment (i.e. conduit, cable whatwever) in the route network",
                arguments: new QueryArguments(
                    new QueryArgument <NonNullGraphType <IdGraphType> > {
                Name = "spanEquipmentId"
            },
                    new QueryArgument <NonNullGraphType <IdGraphType> > {
                Name = "spanEquipmentSpecificationId"
            },
                    new QueryArgument <NonNullGraphType <ListGraphType <IdGraphType> > > {
                Name = "routeSegmentIds"
            },
                    new QueryArgument <IdGraphType> {
                Name = "manufacturerId"
            },
                    new QueryArgument <MarkingInfoInputType> {
                Name = "markingInfo"
            },
                    new QueryArgument <NamingInfoInputType> {
                Name = "namingInfo"
            },
                    new QueryArgument <AddressInfoInputType> {
                Name = "addressInfo"
            }
                    ),
                resolve: async context =>
            {
                var spanEquipmentId = context.GetArgument <Guid>("spanEquipmentId");
                var spanEquipmentSpecificationId = context.GetArgument <Guid>("spanEquipmentSpecificationId");
                var routeSegmentIds = context.GetArgument <List <Guid> >("routeSegmentIds");
                var manufacturerId  = context.GetArgument <Guid>("manufacturerId");
                var markingInfo     = context.GetArgument <MarkingInfo>("markingInfo");
                var namingInfo      = context.GetArgument <NamingInfo>("namingInfo");
                var addressInfo     = context.GetArgument <AddressInfo>("addressInfo");

                // Name conduit span equipment
                // TODO: Refactor into som class responsible for span equipment naming
                var spec   = eventStore.Projections.Get <SpanEquipmentSpecificationsProjection>().Specifications[spanEquipmentSpecificationId];
                namingInfo = CalculateName(eventStore, namingInfo, spec);

                var correlationId = Guid.NewGuid();

                var userContext = context.UserContext as GraphQLUserContext;
                var userName    = userContext.Username;

                // TODO: Get from work manager
                var workTaskId         = Guid.Parse("54800ae5-13a5-4b03-8626-a63b66a25568");
                var commandUserContext = new UserContext(userName, workTaskId);

                var spanEquipments = eventStore.Projections.Get <UtilityNetworkProjection>().SpanEquipmentsByEquipmentId;

                // First register the walk in the route network where the client want to place the span equipment
                var walkOfInterestId = Guid.NewGuid();
                var walk             = new RouteNetworkElementIdList();
                walk.AddRange(routeSegmentIds);

                var registerWalkOfInterestCommand = new RegisterWalkOfInterest(correlationId, commandUserContext, walkOfInterestId, walk);

                var registerWalkOfInterestCommandResult = await commandDispatcher.HandleAsync <RegisterWalkOfInterest, Result <RouteNetworkInterest> >(registerWalkOfInterestCommand);

                if (registerWalkOfInterestCommandResult.IsFailed)
                {
                    return(new CommandResult(registerWalkOfInterestCommandResult));
                }

                // Now place the conduit in the walk
                var placeSpanEquipmentCommand = new PlaceSpanEquipmentInRouteNetwork(
                    correlationId, commandUserContext, spanEquipmentId, spanEquipmentSpecificationId, registerWalkOfInterestCommandResult.Value)
                {
                    ManufacturerId = manufacturerId,
                    NamingInfo     = namingInfo,
                    MarkingInfo    = markingInfo,
                    LifecycleInfo  = new LifecycleInfo(DeploymentStateEnum.InService, null, null),
                    AddressInfo    = addressInfo
                };

                var placeSpanEquipmentResult = await commandDispatcher.HandleAsync <PlaceSpanEquipmentInRouteNetwork, Result>(placeSpanEquipmentCommand);

                // Unregister interest if place span equipment failed
                if (placeSpanEquipmentResult.IsFailed)
                {
                    var unregisterCommandResult = await commandDispatcher.HandleAsync <UnregisterInterest, Result>(
                        new UnregisterInterest(correlationId, commandUserContext, walkOfInterestId));

                    if (unregisterCommandResult.IsFailed)
                    {
                        return(new CommandResult(unregisterCommandResult));
                    }
                }

                return(new CommandResult(placeSpanEquipmentResult));
            }
                );

            FieldAsync <CommandResultType>(
                "affixSpanEquipmentToNodeContainer",
                description: "Affix a span equipment to a node container - i.e. to some condult closure, man hole etc.",
                arguments: new QueryArguments(
                    new QueryArgument <NonNullGraphType <ListGraphType <IdGraphType> > > {
                Name = "spanSegmentIds"
            },
                    new QueryArgument <NonNullGraphType <IdGraphType> > {
                Name = "nodeContainerId"
            },
                    new QueryArgument <NonNullGraphType <NodeContainerSideEnumType> > {
                Name = "nodeContainerSide"
            }
                    ),
                resolve: async context =>
            {
                var spanSegmentIds  = context.GetArgument <List <Guid> >("spanSegmentIds");
                var nodeContainerId = context.GetArgument <Guid>("nodeContainerId");
                var side            = context.GetArgument <NodeContainerSideEnum>("nodeContainerSide");

                var correlationId = Guid.NewGuid();

                var userContext = context.UserContext as GraphQLUserContext;
                var userName    = userContext.Username;

                // TODO: Get from work manager
                var workTaskId = Guid.Parse("54800ae5-13a5-4b03-8626-a63b66a25568");

                var commandUserContext = new UserContext(userName, workTaskId);

                foreach (var spanSegmentId in spanSegmentIds)
                {
                    var affixCommand = new AffixSpanEquipmentToNodeContainer(correlationId, commandUserContext, spanSegmentId, nodeContainerId, side);

                    var affixCommandResult = await commandDispatcher.HandleAsync <AffixSpanEquipmentToNodeContainer, Result>(affixCommand);

                    if (affixCommandResult.IsFailed)
                    {
                        return(new CommandResult(affixCommandResult));
                    }
                }

                return(new CommandResult(Result.Ok()));
            }
                );

            FieldAsync <CommandResultType>(
                "detachSpanEquipmentFromNodeContainer",
                description: "Detach a span equipment from a node container - i.e. from some condult closure, man hole etc.",
                arguments: new QueryArguments(
                    new QueryArgument <ListGraphType <IdGraphType> > {
                Name = "spanSegmentIds"
            },
                    new QueryArgument <NonNullGraphType <IdGraphType> > {
                Name = "routeNodeId"
            }
                    ),
                resolve: async context =>
            {
                var spanSegmentIds = context.GetArgument <List <Guid> >("spanSegmentIds");
                var routeNodeId    = context.GetArgument <Guid>("routeNodeId");

                var correlationId = Guid.NewGuid();

                var userContext = context.UserContext as GraphQLUserContext;
                var userName    = userContext.Username;

                // TODO: Get from work manager
                var workTaskId = Guid.Parse("54800ae5-13a5-4b03-8626-a63b66a25568");

                var commandUserContext = new UserContext(userName, workTaskId)
                {
                    EditingRouteNodeId = routeNodeId
                };

                foreach (var spanSegmentId in spanSegmentIds)
                {
                    var detachCommand       = new DetachSpanEquipmentFromNodeContainer(correlationId, commandUserContext, spanSegmentId, routeNodeId);
                    var detachCommandResult = await commandDispatcher.HandleAsync <DetachSpanEquipmentFromNodeContainer, Result>(detachCommand);

                    if (detachCommandResult.IsFailed)
                    {
                        return(new CommandResult(detachCommandResult));
                    }
                }

                return(new CommandResult(Result.Ok()));
            }
                );

            FieldAsync <CommandResultType>(
                "cutSpanSegments",
                description: "Cut the span segments belonging to som span equipment at the route node specified",
                arguments: new QueryArguments(
                    new QueryArgument <NonNullGraphType <IdGraphType> > {
                Name = "routeNodeId"
            },
                    new QueryArgument <NonNullGraphType <ListGraphType <IdGraphType> > > {
                Name = "spanSegmentstoCut"
            }
                    ),
                resolve: async context =>
            {
                var routeNodeId      = context.GetArgument <Guid>("routeNodeId");
                var spanSegmentToCut = context.GetArgument <Guid[]>("spanSegmentstoCut");

                var correlationId = Guid.NewGuid();

                var userContext = context.UserContext as GraphQLUserContext;
                var userName    = userContext.Username;

                // TODO: Get from work manager
                var workTaskId = Guid.Parse("54800ae5-13a5-4b03-8626-a63b66a25568");

                var commandUserContext = new UserContext(userName, workTaskId)
                {
                    EditingRouteNodeId = routeNodeId
                };

                var cutCmd    = new CutSpanSegmentsAtRouteNode(correlationId, commandUserContext, routeNodeId, spanSegmentToCut);
                var cutResult = await commandDispatcher.HandleAsync <CutSpanSegmentsAtRouteNode, Result>(cutCmd);

                return(new CommandResult(cutResult));
            }
                );

            FieldAsync <CommandResultType>(
                "connectSpanSegments",
                description: "Connect the span segments belonging to two different span equipment at the route node specified",
                arguments: new QueryArguments(
                    new QueryArgument <NonNullGraphType <IdGraphType> > {
                Name = "routeNodeId"
            },
                    new QueryArgument <NonNullGraphType <ListGraphType <IdGraphType> > > {
                Name = "spanSegmentsToConnect"
            }
                    ),
                resolve: async context =>
            {
                var routeNodeId          = context.GetArgument <Guid>("routeNodeId");
                var spanSegmentToConnect = context.GetArgument <Guid[]>("spanSegmentsToConnect");

                var correlationId = Guid.NewGuid();

                var userContext = context.UserContext as GraphQLUserContext;
                var userName    = userContext.Username;

                // TODO: Get from work manager
                var workTaskId = Guid.Parse("54800ae5-13a5-4b03-8626-a63b66a25568");

                var commandUserContext = new UserContext(userName, workTaskId)
                {
                    EditingRouteNodeId = routeNodeId
                };

                var connectCmd    = new ConnectSpanSegmentsAtRouteNode(correlationId, commandUserContext, routeNodeId, spanSegmentToConnect);
                var connectResult = await commandDispatcher.HandleAsync <ConnectSpanSegmentsAtRouteNode, Result>(connectCmd);

                return(new CommandResult(connectResult));
            }
                );

            FieldAsync <CommandResultType>(
                "disconnectSpanSegments",
                description: "Disconnect two span segments belonging to two different span equipment at the route node specified",
                arguments: new QueryArguments(
                    new QueryArgument <NonNullGraphType <IdGraphType> > {
                Name = "routeNodeId"
            },
                    new QueryArgument <NonNullGraphType <ListGraphType <IdGraphType> > > {
                Name = "spanSegmentsToDisconnect"
            }
                    ),
                resolve: async context =>
            {
                var routeNodeId             = context.GetArgument <Guid>("routeNodeId");
                var spanSegmentToDisconnect = context.GetArgument <Guid[]>("spanSegmentsToDisconnect");

                var correlationId = Guid.NewGuid();

                var userContext = context.UserContext as GraphQLUserContext;
                var userName    = userContext.Username;

                // TODO: Get from work manager
                var workTaskId = Guid.Parse("54800ae5-13a5-4b03-8626-a63b66a25568");

                var commandUserContext = new UserContext(userName, workTaskId)
                {
                    EditingRouteNodeId = routeNodeId
                };

                var disconnectCmd    = new DisconnectSpanSegmentsAtRouteNode(correlationId, commandUserContext, routeNodeId, spanSegmentToDisconnect);
                var disconnectResult = await commandDispatcher.HandleAsync <DisconnectSpanSegmentsAtRouteNode, Result>(disconnectCmd);

                return(new CommandResult(disconnectResult));
            }
                );

            FieldAsync <CommandResultType>(
                "addAdditionalInnerSpanStructures",
                description: "Add inner span structures to an existing span equipment",
                arguments: new QueryArguments(
                    new QueryArgument <NonNullGraphType <IdGraphType> > {
                Name = "spanEquipmentOrSegmentId"
            },
                    new QueryArgument <NonNullGraphType <ListGraphType <IdGraphType> > > {
                Name = "spanStructureSpecificationIds"
            }
                    ),
                resolve: async context =>
            {
                var spanEquipmentOrSegmentId = context.GetArgument <Guid>("spanEquipmentOrSegmentId");
                var specificationsId         = context.GetArgument <Guid[]>("spanStructureSpecificationIds");

                var correlationId = Guid.NewGuid();

                var userContext = context.UserContext as GraphQLUserContext;
                var userName    = userContext.Username;

                // TODO: Get from work manager
                var workTaskId = Guid.Parse("54800ae5-13a5-4b03-8626-a63b66a25568");

                var commandUserContext = new UserContext(userName, workTaskId);

                var addStructure = new PlaceAdditionalStructuresInSpanEquipment(
                    correlationId: correlationId,
                    userContext: commandUserContext,
                    spanEquipmentId: spanEquipmentOrSegmentId,
                    structureSpecificationIds: specificationsId
                    );

                var addStructureResult = await commandDispatcher.HandleAsync <PlaceAdditionalStructuresInSpanEquipment, Result>(addStructure);

                return(new CommandResult(addStructureResult));
            }
                );

            FieldAsync <CommandResultType>(
                "removeSpanStructure",
                description: "Remove inner or outer span structure of a span equipment. When the outer span structure is removed the entire span equipment is removed from the network.",
                arguments: new QueryArguments(
                    new QueryArgument <NonNullGraphType <IdGraphType> > {
                Name = "spanSegmentId"
            }
                    ),
                resolve: async context =>
            {
                var spanSegmentId = context.GetArgument <Guid>("spanSegmentId");

                var correlationId = Guid.NewGuid();

                var userContext = context.UserContext as GraphQLUserContext;
                var userName    = userContext.Username;

                // TODO: Get from work manager
                var workTaskId = Guid.Parse("54800ae5-13a5-4b03-8626-a63b66a25568");

                var commandUserContext = new UserContext(userName, workTaskId);

                var removeStructure = new RemoveSpanStructureFromSpanEquipment(
                    correlationId: correlationId,
                    userContext: commandUserContext,
                    spanSegmentId: spanSegmentId
                    );

                var removeStructureResult = await commandDispatcher.HandleAsync <RemoveSpanStructureFromSpanEquipment, Result>(removeStructure);

                return(new CommandResult(removeStructureResult));
            }
                );

            FieldAsync <CommandResultType>(
                "move",
                description: "Move a span equipment / change its walk in the route network",
                arguments: new QueryArguments(
                    new QueryArgument <NonNullGraphType <IdGraphType> > {
                Name = "spanEquipmentOrSegmentId"
            },
                    new QueryArgument <NonNullGraphType <ListGraphType <IdGraphType> > > {
                Name = "routeSegmentIds"
            }
                    ),
                resolve: async context =>
            {
                var spanEquipmentOrSegmentId = context.GetArgument <Guid>("spanEquipmentOrSegmentId");

                var correlationId = Guid.NewGuid();

                var userContext = context.UserContext as GraphQLUserContext;
                var userName    = userContext.Username;

                // TODO: Get from work manager
                var workTaskId = Guid.Parse("54800ae5-13a5-4b03-8626-a63b66a25568");

                var commandUserContext = new UserContext(userName, workTaskId);

                Guid[] routeSegmentIds = context.GetArgument <Guid[]>("routeSegmentIds");

                RouteNetworkElementIdList newWalkIds = new();
                newWalkIds.AddRange(routeSegmentIds);

                var moveCmd = new MoveSpanEquipment(
                    correlationId: correlationId,
                    userContext: commandUserContext,
                    spanEquipmentId: spanEquipmentOrSegmentId,
                    newWalkIds: newWalkIds
                    );

                var moveCmdResult = await commandDispatcher.HandleAsync <MoveSpanEquipment, Result>(moveCmd);

                return(new CommandResult(moveCmdResult));
            }
                );

            FieldAsync <CommandResultType>(
                "updateProperties",
                description: "Mutation that can be used to change the span equipment specification, manufacturer and/or marking information",
                arguments: new QueryArguments(
                    new QueryArgument <NonNullGraphType <IdGraphType> > {
                Name = "spanEquipmentOrSegmentId"
            },
                    new QueryArgument <IdGraphType> {
                Name = "spanEquipmentSpecificationId"
            },
                    new QueryArgument <IdGraphType> {
                Name = "manufacturerId"
            },
                    new QueryArgument <MarkingInfoInputType> {
                Name = "markingInfo"
            },
                    new QueryArgument <AddressInfoInputType> {
                Name = "addressInfo"
            }
                    ),
                resolve: async context =>
            {
                var spanEquipmentOrSegmentId = context.GetArgument <Guid>("spanEquipmentOrSegmentId");

                var correlationId = Guid.NewGuid();

                var userContext = context.UserContext as GraphQLUserContext;
                var userName    = userContext.Username;

                // TODO: Get from work manager
                var workTaskId = Guid.Parse("54800ae5-13a5-4b03-8626-a63b66a25568");

                var commandUserContext = new UserContext(userName, workTaskId);

                var updateCmd = new UpdateSpanEquipmentProperties(correlationId, commandUserContext, spanEquipmentOrSegmentId: spanEquipmentOrSegmentId)
                {
                    SpecificationId = context.HasArgument("spanEquipmentSpecificationId") ? context.GetArgument <Guid>("spanEquipmentSpecificationId") : null,
                    ManufacturerId  = context.HasArgument("manufacturerId") ? context.GetArgument <Guid>("manufacturerId") : null,
                    MarkingInfo     = context.HasArgument("markingInfo") ? context.GetArgument <MarkingInfo>("markingInfo") : null,
                    AddressInfo     = context.HasArgument("addressInfo") ? context.GetArgument <AddressInfo>("addressInfo") : null
                };

                var updateResult = await commandDispatcher.HandleAsync <UpdateSpanEquipmentProperties, Result>(updateCmd);

                return(new CommandResult(updateResult));
            }
                );

            FieldAsync <CommandResultType>(
                "affixSpanEquipmentToParent",
                description: "Affix a span equipment to a parent span equipment - i.e. put a cable inside a conduit",
                arguments: new QueryArguments(
                    new QueryArgument <NonNullGraphType <IdGraphType> > {
                Name = "routeNodeId"
            },
                    new QueryArgument <NonNullGraphType <IdGraphType> > {
                Name = "spanSegmentId1"
            },
                    new QueryArgument <NonNullGraphType <IdGraphType> > {
                Name = "spanSegmentId2"
            }
                    ),
                resolve: async context =>
            {
                var routeNodeId    = context.GetArgument <Guid>("routeNodeId");
                var spanSegmentId1 = context.GetArgument <Guid>("spanSegmentId1");
                var spanSegmentId2 = context.GetArgument <Guid>("spanSegmentId2");

                var correlationId = Guid.NewGuid();

                var userContext = context.UserContext as GraphQLUserContext;
                var userName    = userContext.Username;

                // TODO: Get from work manager
                var workTaskId = Guid.Parse("54800ae5-13a5-4b03-8626-a63b66a25568");

                var commandUserContext = new UserContext(userName, workTaskId);

                var affixCommand       = new AffixSpanEquipmentToParent(correlationId, commandUserContext, routeNodeId, spanSegmentId1, spanSegmentId2);
                var affixCommandResult = await commandDispatcher.HandleAsync <AffixSpanEquipmentToParent, Result>(affixCommand);

                if (affixCommandResult.IsFailed)
                {
                    return(new CommandResult(affixCommandResult));
                }

                return(new CommandResult(Result.Ok()));
            }
                );

            FieldAsync <CommandResultType>(
                "connectToTerminalEquipment",
                description: "Connect one or more span segments inside a span equipment to terminals inside a terminal equipmment",
                arguments: new QueryArguments(
                    new QueryArgument <NonNullGraphType <IdGraphType> > {
                Name = "routeNodeId"
            },
                    new QueryArgument <NonNullGraphType <ListGraphType <ConnectSpanSegmentToTerminalOperationInputType> > > {
                Name = "connects"
            }
                    ),
                resolve: async context =>
            {
                var routeNodeId = context.GetArgument <Guid>("routeNodeId");
                var connects    = context.GetArgument <ConnectSpanSegmentToTerminalOperation[]>("connects");

                var correlationId = Guid.NewGuid();

                var userContext = context.UserContext as GraphQLUserContext;
                var userName    = userContext.Username;

                // TODO: Get from work manager
                var workTaskId = Guid.Parse("54800ae5-13a5-4b03-8626-a63b66a25568");

                var commandUserContext = new UserContext(userName, workTaskId);

                var connectCommand       = new ConnectSpanSegmentsWithTerminalsAtRouteNode(correlationId, commandUserContext, routeNodeId, connects);
                var connectCommandResult = await commandDispatcher.HandleAsync <ConnectSpanSegmentsWithTerminalsAtRouteNode, Result>(connectCommand);

                if (connectCommandResult.IsFailed)
                {
                    return(new CommandResult(connectCommandResult));
                }

                return(new CommandResult(Result.Ok()));
            }
                );

            FieldAsync <CommandResultType>(
                "disconnectFromTerminalEquipment",
                description: "Disconnect one or more span segments inside a span equipment from terminals inside a terminal equipmment",
                arguments: new QueryArguments(
                    new QueryArgument <NonNullGraphType <IdGraphType> > {
                Name = "routeNodeId"
            },
                    new QueryArgument <NonNullGraphType <ListGraphType <DisconnectSpanSegmentFromTerminalOperationInputType> > > {
                Name = "disconnects"
            }
                    ),
                resolve: async context =>
            {
                var routeNodeId = context.GetArgument <Guid>("routeNodeId");
                var connects    = context.GetArgument <DisconnectSpanSegmentFromTerminalOperation[]>("disconnects");

                var correlationId = Guid.NewGuid();

                var userContext = context.UserContext as GraphQLUserContext;
                var userName    = userContext.Username;

                // TODO: Get from work manager
                var workTaskId = Guid.Parse("54800ae5-13a5-4b03-8626-a63b66a25568");

                var commandUserContext = new UserContext(userName, workTaskId);
                var connectCommand     = new DisconnectSpanSegmentsFromTerminalsAtRouteNode(correlationId, commandUserContext, routeNodeId, connects);

                var connectCommandResult = await commandDispatcher.HandleAsync <DisconnectSpanSegmentsFromTerminalsAtRouteNode, Result>(connectCommand);

                if (connectCommandResult.IsFailed)
                {
                    return(new CommandResult(connectCommandResult));
                }

                return(new CommandResult(Result.Ok()));
            }
                );
        }
        private Result PlaceConduitSpanEquipment(NpgsqlCommand logCmd, Guid spanEquipmentId, string externalId, Guid specificationId, List <Guid> segmentIds, List <Guid> additionalStructureSpecIds, string markingColor, Guid?accessAddressId, Guid?unitAddressId, string?addressRemark)
        {
            Guid correlationId = Guid.NewGuid();

            RouteNetworkElementIdList walkIds = new RouteNetworkElementIdList();

            walkIds.AddRange(segmentIds);

            // Register walk of interest
            var walkOfInterestId = Guid.NewGuid();
            var registerWalkOfInterestCommand = new RegisterWalkOfInterest(correlationId, new UserContext("conversion", _neMultiConduitConversion), walkOfInterestId, walkIds);

            var registerWalkOfInterestCommandResult = _commandDispatcher.HandleAsync <RegisterWalkOfInterest, Result <RouteNetworkInterest> >(registerWalkOfInterestCommand).Result;

            if (registerWalkOfInterestCommandResult.IsFailed)
            {
                _logger.LogInformation("Failed to add conduit: " + externalId + " Error: " + registerWalkOfInterestCommandResult.Errors.First().Message);
                LogStatus((NpgsqlCommand)logCmd, _tableName, registerWalkOfInterestCommandResult.Errors.First().Message, externalId);
                return(registerWalkOfInterestCommandResult);
            }

            // conduit name
            var nextConduitSeqStr = _eventStore.Sequences.GetNextVal("conduit").ToString();

            var conduitName = "R" + nextConduitSeqStr.PadLeft(6, '0');
            var namingInfo  = new NamingInfo(conduitName, null);

            AddressInfo?addressInfo = null;

            if (accessAddressId != null || unitAddressId != null && addressRemark != null)
            {
                addressInfo = new AddressInfo()
                {
                    AccessAddressId = accessAddressId, UnitAddressId = unitAddressId, Remark = addressRemark
                };
            }

            // Place conduit
            var placeSpanEquipmentCommand = new PlaceSpanEquipmentInRouteNetwork(correlationId, new UserContext("conversion", _neMultiConduitConversion), spanEquipmentId, specificationId, registerWalkOfInterestCommandResult.Value)
            {
                MarkingInfo = markingColor != null ? new MarkingInfo()
                {
                    MarkingColor = markingColor
                } : null,
                NamingInfo  = namingInfo,
                AddressInfo = addressInfo
            };

            var placeSpanEquipmentResult = _commandDispatcher.HandleAsync <PlaceSpanEquipmentInRouteNetwork, Result>(placeSpanEquipmentCommand).Result;

            if (placeSpanEquipmentResult.IsFailed)
            {
                _logger.LogInformation("Failed to add conduit: " + externalId + " Error: " + placeSpanEquipmentResult.Errors.First().Message);
                LogStatus((NpgsqlCommand)logCmd, _tableName, placeSpanEquipmentResult.Errors.First().Message, externalId);
                return(placeSpanEquipmentResult);
            }

            // Place additional structures
            if (additionalStructureSpecIds.Count > 0)
            {
                var addStructure = new PlaceAdditionalStructuresInSpanEquipment(correlationId, new UserContext("conversion", _neMultiConduitConversion),
                                                                                spanEquipmentId: placeSpanEquipmentCommand.SpanEquipmentId,
                                                                                structureSpecificationIds: additionalStructureSpecIds.ToArray()
                                                                                );

                var addStructureResult = _commandDispatcher.HandleAsync <PlaceAdditionalStructuresInSpanEquipment, Result>(addStructure).Result;

                if (addStructureResult.IsFailed)
                {
                    _logger.LogInformation("Failed to add additional structures to: " + externalId + " Error: " + placeSpanEquipmentResult.Errors.First().Message);
                    LogStatus((NpgsqlCommand)logCmd, _tableName, addStructureResult.Errors.First().Message, externalId);
                    return(addStructureResult);
                }
            }

            return(Result.Ok());
        }