public static DeliveryFormMailerModel GetDeliveryFormModel(Domain.User producer, Domain.User client,
                                                                   Domain.Delivery delivery, string producerSiret = null, string clientSiret = null)
        {
            var purchaseOrders = GetPurchaseOrders(delivery.PurchaseOrders);

            var productsToDeliver = delivery.Products
                                    .Where(p => p.RowKind == ModificationKind.ToDeliver)
                                    .Select(p => GetProductModel(p, p.RowKind))
                                    .ToList();

            var productsDiffs = delivery.Products
                                .Where(p => p.RowKind != ModificationKind.ToDeliver)
                                .Select(p => GetProductModel(p, p.RowKind))
                                .ToList();

            var returnablesDiffs = delivery.Products
                                   .Where(p => p.RowKind != ModificationKind.ToDeliver && p.HasReturnable)
                                   .GroupBy(p => new { p.ReturnableId, p.RowKind })
                                   .Select(p =>
            {
                var returnable = p.First();
                return(new DeliveryReturnableMailerModel
                {
                    Name = returnable.ReturnableName,
                    Quantity = returnable.Quantity,
                    Vat = returnable.ReturnableVat.Value,
                    RowKind = p.Key.RowKind,
                    TotalVatPrice = p.Sum(r => r.TotalReturnableVatPrice.Value),
                    TotalOnSalePrice = p.Sum(r => r.TotalReturnableOnSalePrice.Value),
                    TotalWholeSalePrice = p.Sum(r => r.TotalReturnableWholeSalePrice.Value),
                    WholeSalePrice = returnable.ReturnableWholeSalePrice.Value
                });
            }).ToList();

            var returnedReturnables = delivery.ReturnedReturnables?
                                      .Select(GetReturnedReturnableModel)
                                      .ToList() ?? new List <DeliveryReturnableMailerModel>();

            var vat5Price  = GetVatPriceForPercent(productsToDeliver, productsDiffs, returnedReturnables, 5.5m);
            var vat10Price = GetVatPriceForPercent(productsToDeliver, productsDiffs, returnedReturnables, 10m);
            var vat20Price = GetVatPriceForPercent(productsToDeliver, productsDiffs, returnedReturnables, 20m) + delivery.DeliveryFeesVatPrice;

            return(new DeliveryFormMailerModel()
            {
                Identifier = delivery.Reference.AsDeliveryIdentifier(),
                Producer = GetUserModel(producer, producerSiret),
                Client = GetUserModel(client, clientSiret),
                PurchaseOrders = purchaseOrders,
                ProductsToDeliver = productsToDeliver,
                ProductsDiffs = productsDiffs,
                ReturnedReturnables = returnedReturnables,
                ReturnablesDiffs = returnablesDiffs,
                DeliveredOn = delivery.DeliveredOn ?? delivery.ScheduledOn,
                ScheduledOn = delivery.ScheduledOn,
                ReceptionnedBy = delivery.ReceptionedBy,
                Comment = delivery.Comment,
                DeliveryFeesWholeSalePrice = delivery.DeliveryFeesWholeSalePrice,
                DeliveryFeesVatPrice = delivery.DeliveryFeesVatPrice,
                DeliveryFeesOnSalePrice = delivery.DeliveryFeesOnSalePrice,
                TotalWholeSalePrice = productsToDeliver.Sum(po => po.TotalWholeSalePrice) +
                                      productsDiffs.Sum(p => p.TotalWholeSalePrice) +
                                      returnedReturnables.Sum(p => p.TotalWholeSalePrice) +
                                      delivery.DeliveryFeesWholeSalePrice,
                TotalVat5Price = vat5Price,
                TotalVat10Price = vat10Price,
                TotalVat20Price = vat20Price,
                TotalVatPrice = vat5Price + vat10Price + vat20Price,
                TotalOnSalePrice = productsToDeliver.Sum(po => po.TotalOnSalePrice) +
                                   productsDiffs.Sum(p => p.TotalOnSalePrice) +
                                   returnedReturnables.Sum(p => p.TotalOnSalePrice) +
                                   delivery.DeliveryFeesOnSalePrice,
            });
        }
Exemple #2
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));