protected async Task UpdateParcelStatusAsync(Guid parcelId, Action <Parcel> update)
        {
            var parcel = await _parcelsRepository.GetAsync(parcelId);

            update(parcel);
            await _parcelsRepository.UpdateAsync(parcel);
        }
Example #2
0
        public async Task HandleAsync(DeliveryCompleted @event)
        {
            var parcel = await _parcelsRepository.GetAsync(@event.ParcelId);

            if (parcel is null)
            {
                throw new InvalidOperationException($"Parcel with id: {@event.ParcelId} was not found.");
            }

            parcel.CompleteDelivery();
            await _parcelsRepository.UpdateAsync(parcel);

            _logger.LogInformation($"The delivery for parcel with id: {@event.ParcelId} has completed.");
        }
Example #3
0
        public async Task<ParcelDto> GetAsync(Guid id)
        {
            var parcel = await _parcelsRepository.GetAsync(id);

            return parcel is null
                ? null
                : new ParcelDto
                {
                    Id = parcel.Id,
                    Address = parcel.Address,
                    Size = parcel.Size.ToString().ToLowerInvariant(),
                    State = parcel.State.ToString()
                };
        }
Example #4
0
        public async Task HandleAsync(StartDelivery command)
        {
            if (command.Parcels is null)
            {
                throw new Exception("Parcels to be delivered were not specified.");
            }

            var parcels = new HashSet <Parcel>();

            foreach (var parcelId in command.Parcels)
            {
                var parcel = await _parcelsRepository.GetAsync(parcelId);

                if (parcel is null)
                {
                    throw new Exception($"Parcel with id: {parcelId} to be delivered was not found.");
                }

                if (await _deliveriesRepository.IsParcelInDeliveryAsync(parcelId))
                {
                    throw new Exception($"Parcel with id: {parcelId} is unavailable.");
                }

                parcels.Add(parcel);
            }

            if (!parcels.Any())
            {
                throw new Exception($"Delivery cannot be started without the parcels.");
            }

            _logger.LogInformation("Calculating the route...");
            var route = await _routingServiceClient.GetAsync(parcels.Select(p => p.Address));

            if (route is null)
            {
                throw new Exception("Route was not found.");
            }

            _logger.LogInformation("Route was calculated.");
            await _deliveriesRepository.AddAsync(new Delivery(command.DeliveryId, parcels,
                                                              new Route(route.Addresses, route.TotalDistance)));

            var eventsToPublish = parcels.Select(p => _messageBroker.PublishAsync(
                                                     new DeliveryStarted(command.DeliveryId, p.Id)));
            await Task.WhenAll(eventsToPublish);

            _logger.LogInformation($"Started a delivery with id: {command.DeliveryId}");
        }
        public async Task HandleAsync(DeliveryFailed @event)
        {
            var parcel = await _parcelsRepository.GetAsync(@event.ParcelId);

            if (parcel is null)
            {
                throw new InvalidOperationException($"Parcel with id: {@event.ParcelId} was not found.");
            }

            parcel.FailDelivery(@event.Reason);
            await _parcelsRepository.UpdateAsync(parcel);

            _logger.LogInformation($"The delivery for parcel with id: {@event.ParcelId} has failed " +
                                   $"reason: {@event.Reason}.");
        }
Example #6
0
        public async Task <ParcelDetailsDto> HandleAsync(GetParcel query)
        {
            var parcel = await _parcelsRepository.GetAsync(query.ParcelId);

            return(parcel is null
                ? null
                : new ParcelDetailsDto
            {
                Id = parcel.Id,
                Address = parcel.Address,
                Name = parcel.Name,
                Notes = parcel.Notes,
                Size = parcel.Size.ToString(),
                Status = parcel.Status.ToString()
            });
        }
Example #7
0
        public async Task HandleAsync(DeleteParcel command)
        {
            var parcel = await _parcelsRepository.GetAsync(command.ParcelId);

            if (parcel is null)
            {
                throw new Exception($"Parcel: {command.ParcelId:N} was not found.");
            }

            if (parcel.Status != Status.Available)
            {
                throw new Exception($"Parcel: {command.ParcelId:N} cannot be deleted, status: {parcel.Status}.");
            }

            await _parcelsRepository.DeleteAsync(command.ParcelId);

            _logger.LogInformation($"Deleted a parcel: {command.ParcelId:N}.");
            await _dispatcher.PublishAsync(new ParcelDeleted(command.ParcelId));
        }
        public async Task HandleAsync(DeleteParcel command)
        {
            var parcel = await _parcelsRepository.GetAsync(command.ParcelId);

            if (parcel is null)
            {
                throw new Exception($"Parcel with id: {command.ParcelId} was not found.");
            }

            if (parcel.Status != Status.New)
            {
                throw new InvalidOperationException($"Parcel with id: {command.ParcelId} " +
                                                    $"and status: {parcel.Status} cannot be deleted.");
            }

            await _parcelsRepository.DeleteAsync(command.ParcelId);

            await _messageBroker.PublishAsync(new ParcelDeleted(command.ParcelId));

            _logger.LogInformation($"Deleted a parcel with id: {command.ParcelId}");
        }
        public async Task HandleAsync(DeliveryStatusChanged @event)
        {
            var deliveryDto = Map(@event.Delivery);
            var parcels     = new List <ParcelInDeliveryDto>();

            foreach (var parcelDto in deliveryDto.Parcels)
            {
                var parcel = await _parcelsRepository.GetAsync(parcelDto.Id);

                parcels.Add(new ParcelInDeliveryDto
                {
                    Id      = parcel.Id,
                    Name    = parcel.Name,
                    Address = parcel.Address
                });
            }

            deliveryDto.Parcels = parcels;

            await _storage.SetAsync(deliveryDto);

            _logger.LogInformation($"Set DTO for delivery: {@event.Delivery.Id} in storage.");
        }
Example #10
0
        public async Task HandleAsync(StartDelivery command)
        {
            if (command.Parcels is null)
            {
                throw new Exception("Parcels to be delivered were not specified.");
            }

            var parcels = new HashSet <Parcel>();

            foreach (var parcelId in command.Parcels)
            {
                var parcel = await _parcelsRepository.GetAsync(parcelId);

                if (parcel is null)
                {
                    throw new Exception($"Parcel: {parcelId:N} to be delivered was not found.");
                }

                if (await _deliveriesRepository.HasParcelInDelivery(parcelId))
                {
                    throw new Exception($"Parcel: {parcelId:N} is unavailable.");
                }

                parcels.Add(parcel);
            }

            if (!parcels.Any())
            {
                throw new Exception($"Delivery cannot be started without the parcels.");
            }

            _logger.LogInformation("Calculating the route...");
            var route = await _routingServiceClient.GetAsync(parcels.Select(p => p.Address));

            if (route is null)
            {
                throw new Exception("Route was not found.");
            }

            _logger.LogInformation("Route was calculated.");
            var delivery = new Delivery(command.DeliveryId, parcels.Select(p => p.Id),
                                        new Route(route.Addresses, route.Distance));

            delivery.Start();
            await _deliveriesRepository.AddAsync(delivery);

            _logger.LogInformation($"Started a delivery: {command.DeliveryId:N}");

            var domainEvents = delivery.Events;

            foreach (var domainEvent in domainEvents)
            {
                await _domainEventPublisher.PublishAsync(domainEvent);
            }

            delivery.ClearEvents();

            var events = parcels.Select(p => new DeliveryStarted(command.DeliveryId, p.Id));

            foreach (var @event in events)
            {
                await _dispatcher.PublishAsync(@event);
            }
        }