Example #1
0
        public async Task <Result> Handle(UpdateDeliveryBatchCommand request, CancellationToken token)
        {
            var deliveryBatch = await _context.DeliveryBatches.SingleOrDefaultAsync(c => c.Id == request.Id, token);

            if (deliveryBatch == null)
            {
                return(Failure("La tournée de livraison est introuvable."));
            }

            if (deliveryBatch.Status != DeliveryBatchStatus.Waiting)
            {
                return(Failure("Impossible de modifier une livraison qui n'est pas en attente."));
            }

            var clientIds         = request.Deliveries.Select(d => d.ClientId);
            var existingClientIds = deliveryBatch.Deliveries.Select(d => d.ClientId);

            var deliveriesToRemove = existingClientIds.Except(clientIds);

            foreach (var clientIdToRemove in deliveriesToRemove)
            {
                var delivery = deliveryBatch.Deliveries.Single(d => d.ClientId == clientIdToRemove);
                deliveryBatch.RemoveDelivery(delivery);
                _context.Remove(delivery);
            }

            var currentPosition = 0;

            foreach (var clientDelivery in request.Deliveries.OrderBy(d => d.Position))
            {
                var delivery       = deliveryBatch.Deliveries.SingleOrDefault(d => d.ClientId == clientDelivery.ClientId);
                var purchaseOrders = await _context.PurchaseOrders
                                     .Where(p => clientDelivery.PurchaseOrderIds.Contains(p.Id))
                                     .ToListAsync(token);

                if (purchaseOrders.Any(po => po.Status != PurchaseOrderStatus.Completed))
                {
                    throw SheaftException.Validation("Certaines commandes ne sont pas prête.");
                }

                if (purchaseOrders.Any(po => (int)po.ExpectedDelivery.Kind <= 4))
                {
                    throw SheaftException.Validation("Certaines commandes doivent être récupérée et non livrée.");
                }

                if (delivery == null)
                {
                    var order = purchaseOrders.First();
                    var user  = await _context.Users.SingleAsync(u => u.Id == order.ClientId, token);

                    var identifier = await _identifierService.GetNextDeliveryReferenceAsync(deliveryBatch.AssignedTo.Id, token);

                    if (!identifier.Succeeded)
                    {
                        return(Failure(identifier));
                    }

                    delivery = new Domain.Delivery(identifier.Data, (Domain.Producer)deliveryBatch.AssignedTo,
                                                   order.ExpectedDelivery.Kind,
                                                   deliveryBatch.ScheduledOn, order.ExpectedDelivery.Address, user.Id, user.Name, purchaseOrders,
                                                   currentPosition);

                    deliveryBatch.AddDelivery(delivery);
                }
                else
                {
                    var existingPurchaseOrderIds = delivery.PurchaseOrders.Select(po => po.Id);
                    var newPurchaseOrderIds      = purchaseOrders.Select(po => po.Id);
                    var purchaseOrderIdsToRemove = existingPurchaseOrderIds.Except(newPurchaseOrderIds).ToList();
                    if (purchaseOrderIdsToRemove.Any())
                    {
                        var purchaseOrdersToRemove =
                            delivery.PurchaseOrders.Where(po => purchaseOrderIdsToRemove.Contains(po.Id));

                        delivery.RemovePurchaseOrders(purchaseOrdersToRemove);
                    }

                    foreach (var purchaseOrder in purchaseOrders)
                    {
                        var existingPurchaseOrder =
                            delivery.PurchaseOrders.SingleOrDefault(po => po.Id == purchaseOrder.Id);
                        if (existingPurchaseOrder == null)
                        {
                            delivery.AddPurchaseOrders(new[] { purchaseOrder });
                        }
                    }
                }

                delivery.SetPosition(currentPosition);
                currentPosition++;
            }

            deliveryBatch.SetName(request.Name);
            await _context.SaveChangesAsync(token);

            var result = await _mediatr.Process(new GenerateDeliveryBatchDocumentsCommand(request.RequestUser){ Id = deliveryBatch.Id }, token);

            return(result is { Succeeded : false } ? Failure(result) : Success());
        public async Task <Result <Guid> > Handle(CreateDeliveryBatchCommand request, CancellationToken token)
        {
            var purchaseOrders = await GetPurchaseOrdersAsync(request, token);

            if (purchaseOrders.Any(po => po.Status == PurchaseOrderStatus.Delivered))
            {
                return(Failure <Guid>("Certaines commandes ont déjà été livrées."));
            }

            if (purchaseOrders.Any(po => (int)po.ExpectedDelivery.Kind <= 4))
            {
                return(Failure <Guid>("Impossible d'ajouter des commandes qui sont à récupérer par le client."));
            }

            var name     = GetDeliveryBatchName(request, purchaseOrders);
            var producer = await _context.Producers.SingleAsync(p => p.Id == request.ProducerId, token);

            var usersAgreements = await GetUsersPositionsAsync(request, token, purchaseOrders);

            var purchaseOrderIds         = request.Deliveries.SelectMany(d => d.PurchaseOrderIds);
            var purchaseOrdersDeliveries =
                await _context.Deliveries.Where(d => d.PurchaseOrders.Any(po => purchaseOrderIds.Contains(po.Id)))
                .Include(d => d.PurchaseOrders)
                .ToListAsync(token);

            var deliveries = new List <Domain.Delivery>();

            foreach (var delivery in purchaseOrdersDeliveries)
            {
                var assignedPurchaseOrders = delivery.PurchaseOrders
                                             .Where(po => purchaseOrderIds.Contains(po.Id))
                                             .ToList();

                if (delivery.PurchaseOrders.Count == assignedPurchaseOrders.Count)
                {
                    if (delivery.DeliveryBatchId.HasValue && delivery.DeliveryBatch.ScheduledOn != request.ScheduledOn)
                    {
                        delivery.PostponeDelivery();
                    }

                    deliveries.Add(delivery);

                    foreach (var assignedPurchaseOrder in assignedPurchaseOrders)
                    {
                        var pendingPurchaseOrder = purchaseOrders.Single(po => po.Id == assignedPurchaseOrder.Id);
                        purchaseOrders.Remove(pendingPurchaseOrder);
                    }
                }
                else
                {
                    delivery.RemovePurchaseOrders(assignedPurchaseOrders);

                    var identifier = await _identifierService.GetNextDeliveryReferenceAsync(producer.Id, token);

                    if (!identifier.Succeeded)
                    {
                        return(Failure <Guid>(identifier));
                    }

                    var newDelivery = new Domain.Delivery(identifier.Data, producer, delivery.Kind, request.ScheduledOn,
                                                          delivery.Address,
                                                          delivery.ClientId, delivery.Client, assignedPurchaseOrders, delivery.Position);

                    if (delivery.DeliveryBatch != null && delivery.DeliveryBatch.ScheduledOn != request.ScheduledOn)
                    {
                        newDelivery.PostponeDelivery();
                    }

                    deliveries.Add(newDelivery);
                }
            }

            foreach (var purchaseOrderGrouped in purchaseOrders
                     .GroupBy(p => p.ClientId)
                     .OrderByDescending(e => e.Count())
                     .ToList())
            {
                var order            = purchaseOrderGrouped.First();
                var existingDelivery = deliveries.SingleOrDefault(d => d.ClientId == order.ClientId);
                if (existingDelivery != null)
                {
                    if (existingDelivery.PurchaseOrders.Any(po => po.Id == order.Id))
                    {
                        continue;
                    }

                    existingDelivery.AddPurchaseOrders(new[] { order });
                }
                else
                {
                    var userAgreement = usersAgreements.First(a => a.User.Id == order.ClientId);
                    var position      = userAgreement?.Position ?? 0;
                    while (deliveries.Any(d => d.Position == position))
                    {
                        position++;
                    }

                    var identifier = await _identifierService.GetNextDeliveryReferenceAsync(producer.Id, token);

                    if (!identifier.Succeeded)
                    {
                        return(Failure <Guid>(identifier));
                    }

                    var delivery = new Domain.Delivery(identifier.Data, producer, order.ExpectedDelivery.Kind,
                                                       request.ScheduledOn,
                                                       order.ExpectedDelivery.Address, userAgreement.User.Id, userAgreement.User.Name,
                                                       purchaseOrderGrouped.ToList(), position);

                    deliveries.Add(delivery);
                }
            }

            var deliveryBatch = new Domain.DeliveryBatch(Guid.NewGuid(), name, request.ScheduledOn, request.From,
                                                         producer, deliveries, request.CreatedFromPartialBatchId);

            if (request.CreatedFromPartialBatchId.HasValue)
            {
                foreach (var delivery in deliveries)
                {
                    delivery.PostponeDelivery();
                }
            }

            await _context.AddAsync(deliveryBatch, token);

            await _context.SaveChangesAsync(token);

            if (request.SetAsReady)
            {
                _mediatr.Post(new SetDeliveryBatchAsReadyCommand(request.RequestUser)
                {
                    Id = deliveryBatch.Id
                });
            }

            var result = await _mediatr.Process(new GenerateDeliveryBatchDocumentsCommand(request.RequestUser){ Id = deliveryBatch.Id }, token);

            return(result is { Succeeded : false } ? Failure <Guid>(result) : Success(deliveryBatch.Id));