DetailedBatchSupplyChainQueryData ISupplyChainService.GetDetailedBatchSupplyChain(Guid batchId)
        {
            var result = new DetailedBatchSupplyChainQueryData();

            var transfersOfThatBatch = medicineBatchTransferRepository.GetAll()
                                       .Where(t => t.MedicineBatchId == batchId)
                                       .ToList();

            // Get all last tier transfers
            var higestTier = transfersOfThatBatch.Max(t => t.Tier);
            List <MedicineBatchTransfer> lastTierTransfers = transfersOfThatBatch
                                                             .Where(t => t.Tier == higestTier)
                                                             .ToList();

            result.TransferChains = new List <List <MedicineBatchTransferQueryData> >();

            // Trace backwards
            foreach (var transfer in lastTierTransfers)
            {
                List <MedicineBatchTransferQueryData> transferChain = new List <MedicineBatchTransferQueryData>();
                var iterator     = transfer;
                var transferPool = transfersOfThatBatch;
                bool parentMatchCondition(MedicineBatchTransfer t) => t.ToId == iterator.FromId;

                transferChain.Add(iterator.ToMedicineBatchTransferQueryData());

                while (iterator.HasParent(transferPool, parentMatchCondition))
                {
                    iterator = iterator.Parent(transferPool, parentMatchCondition).Single();
                    transferChain.Add(iterator.ToMedicineBatchTransferQueryData());
                }

                result.TransferChains.Add(transferChain);
            }
            // TODO: Trace tier backwards. There might be missing chains in which transfers have lower tier than the highest one of the whole batch supply chain.

            // Calculate the summary section
            CalculateSummarySection(result);

            // Format the result
            foreach (var chain in result.TransferChains)
            {
                chain.Reverse();
            }

            return(result);
        }
        DetailedBatchSupplyChainQueryData ISupplyChainService.GetBatchSupplyChain(Guid batchId, Guid retailerId)
        {
            var transfersOfThatBatch = medicineBatchTransferRepository.GetAll()
                                       .Where(t => t.MedicineBatchId == batchId)
                                       .ToList();

            var transfersToRetailer = transfersOfThatBatch
                                      .Where(t => t.ToId == retailerId)
                                      .ToList();

            var result = new DetailedBatchSupplyChainQueryData
            {
                TransferChains = new List <List <MedicineBatchTransferQueryData> >()
            };

            foreach (var transfer in transfersToRetailer)
            {
                // Trace backwards to get a full chain of that transfer.
                List <MedicineBatchTransferQueryData> transferChain = new List <MedicineBatchTransferQueryData>();
                var iterator     = transfer;
                var transferPool = transfersOfThatBatch;
                bool parentMatchCondition(MedicineBatchTransfer t) => t.ToId == iterator.FromId;

                transferChain.Add(iterator.ToMedicineBatchTransferQueryData());

                while (iterator.HasParent(transferPool, parentMatchCondition))
                {
                    iterator = iterator.Parent(transferPool, parentMatchCondition).Single();
                    transferChain.Add(iterator.ToMedicineBatchTransferQueryData());
                }

                result.TransferChains.Add(transferChain);
            }

            // Calculate the summary section
            CalculateSummarySection(result);

            // Format the result
            foreach (var chain in result.TransferChains)
            {
                chain.Reverse();
            }

            return(result);
        }
        private static void CalculateSummarySection(DetailedBatchSupplyChainQueryData result)
        {
            var tempTransfers = new List <MedicineBatchTransferQueryData>();

            foreach (var chain in result.TransferChains)
            {
                tempTransfers.AddRange(chain);
            }
            var tempTenants = new List <TenantQueryData>();

            foreach (var transfer in tempTransfers)
            {
                tempTenants.Add(transfer.From);
                tempTenants.Add(transfer.To);
            }
            result.TotalTransfers = (uint)tempTransfers.Count();
            result.TotalTenants   = (uint)tempTenants.GroupBy(t => t.Id).Count();
        }
 public IActionResult GetSupplyChain(Guid batchId,
                                     [FromQuery] bool?isDetailed)
 {
     try
     {
         if (isDetailed.HasValue && isDetailed.Value == true)
         {
             DetailedBatchSupplyChainQueryData result = supplyChainService.GetDetailedBatchSupplyChain(batchId);
             return(Ok(result));
         }
         else
         {
             BatchSupplyChainQueryData result = supplyChainService.GetSimpleBatchSupplyChain(batchId);
             return(Ok(result));
         }
     }
     catch (Exception ex)
     {
         return(StatusCode(StatusCodes.Status500InternalServerError, ex));
     }
 }