private bool SetExceptionTransaction(Facility facility, Formulary formulary, FacilityFormulary facilityFormulary, FacilityStorageSpace storageSpaceInfo, TransactionRequest request, Item item, int quantity, TransactionQueueModel newTransaction)
        {
            var isItemAccepted    = (facilityFormulary != null && facilityFormulary.Approved) ? true : false;
            var isActiveFormulary = (formulary != null && !formulary.IsActive.GetValueOrDefault()) ? false : true;

            if (formulary == null)
            {
                newTransaction.Description = item.ItemName;
                SetTransactionException(newTransaction, CommonConstants.TransactionException.UnknownItemId);
                if (!int.TryParse(item.OrderAmount.Trim(), out quantity))
                {
                    newTransaction.Exception += Environment.NewLine + CommonConstants.TransactionException.InvalidQuantity;
                }
                newTransaction.Quantity = quantity;
                return(true);
            }

            if (!isActiveFormulary)
            {
                SetTransactionException(newTransaction, CommonConstants.TransactionException.InactiveFormularyItem);
                return(true);
            }

            if (facilityFormulary == null)
            {
                SetTransactionException(newTransaction, CommonConstants.TransactionException.FormularyNotMapped);
                return(true);
            }

            if (!isItemAccepted)
            {
                SetTransactionException(newTransaction, CommonConstants.TransactionException.NotApprovedFormularyItem);
                return(true);
            }

            if (quantity <= 0)
            {
                SetTransactionException(newTransaction, CommonConstants.TransactionException.InvalidUnitQuantity);
                return(true);
            }

            if (storageSpaceInfo == null)
            {
                SetTransactionException(newTransaction, CommonConstants.TransactionException.UnassignedLocation);
                return(true);
            }

            return(false);
        }
        /// <summary>
        /// This method processes the aggregated incoming request from Aggregator Service, applies business rules and inserts transaction record.
        /// </summary>
        /// <param name="request">Incoming request</param>
        /// <param name="headers">Headers</param>
        public async Task ProcessTransactionRequest(TransactionRequest request, Dictionary <string, string> headers)
        {
            _logger.LogInformation(string.Format(CommonConstants.LoggingMessage.ProcessIncomingRequest, JsonConvert.SerializeObject(request)));

            var status     = TransactionStatus.Interim;
            var facilityId = request.Facility.FacilityId;
            FacilityStorageSpace storageSpaceInfo = null;
            var priority = await _transactionPriorityManager.ValidatePriority(request.Facility.FacilityId, request.Priority);

            var facility = await _facilityManager.ValidateFacility(facilityId);

            var destination = await _destinationManager.GetDestinationByCode(request?.Patient?.DeliverToLocation);

            if (facility != null)
            {
                if ((facility.AduIgnoreCritLow == true && string.Equals(request.Priority, Priority.PYXISCRITLOW.ToString(), StringComparison.OrdinalIgnoreCase)) ||
                    (facility.AduIgnoreStockout == true && (string.Equals(request.Priority, Priority.PYXISSTOCKOUT.ToString(), StringComparison.OrdinalIgnoreCase) || string.Equals(request.Priority, Priority.PYXISSTKOUT.ToString(), StringComparison.OrdinalIgnoreCase))))
                {
                    _logger.LogInformation(string.Format(CommonConstants.LoggingMessage.RejectedRequest, request.RequestId));
                    status = TransactionStatus.Ignored;
                }

                storageSpaceInfo = facility.StorageSpaces?.Where(x => x.IsDefault).FirstOrDefault();
            }

            var partNo          = 0;
            var multiMedName    = string.Empty;
            var transactionList = new List <TransactionQueueModel>();

            var orderCount       = Enumerable.Count <Item>(request.Items);
            var isMultiComponent = orderCount > 1 ? true : false;

            foreach (var item in request.Items)
            {
                FacilityFormulary facilityFormulary = null;

                var formulary = await _formularyManager.GetFormularyByItemId(item.ItemId);

                if (formulary != null && formulary.FacilityFormulary != null && formulary.FacilityFormulary.FacilityId == facilityId)
                {
                    facilityFormulary = formulary.FacilityFormulary;
                }

                if (facility != null && facilityFormulary != null &&
                    ((string.Equals(request.Priority, Priority.PYXISCRITLOW.ToString(), StringComparison.OrdinalIgnoreCase) && facilityFormulary.AduIgnoreCritLow != null && (bool)facilityFormulary.AduIgnoreCritLow) ||
                     ((string.Equals(request.Priority, Priority.PYXISSTOCKOUT.ToString(), StringComparison.OrdinalIgnoreCase) || string.Equals(request.Priority, Priority.PYXISSTKOUT.ToString(), StringComparison.OrdinalIgnoreCase)) &&
                      facilityFormulary.AduIgnoreStockout != null && (bool)facilityFormulary.AduIgnoreStockout)))
                {
                    status = TransactionStatus.Ignored;
                }

                //Checks for ADUIgnoreCritLow and ADUIgnoreStockOut prior to ADU Cases
                if (priority != null && destination != null &&
                    ((priority.TransactionPriorityCode.ToLower() == Priority.PYXISCRITLOW.ToString().ToLower() &&
                      destination.AduIgnoreCritLow.GetValueOrDefault()) ||
                     ((priority.TransactionPriorityCode.ToLower() == Priority.PYXISSTOCKOUT.ToString().ToLower() || priority.TransactionPriorityCode.ToLower() == Priority.PYXISSTKOUT.ToString().ToLower()) &&
                      destination.AduIgnoreStockOut.GetValueOrDefault())))
                {
                    status = TransactionStatus.Ignored;
                }

                int.TryParse(item.OrderAmount, out int quantity);
                var newTransaction = new TransactionQueueModel();

                if (status != TransactionStatus.Ignored)
                {
                    var isExceptionTransaction = SetExceptionTransaction(facility, formulary, facilityFormulary, storageSpaceInfo, request, item, quantity, newTransaction);

                    if (!isExceptionTransaction)
                    {
                        SetValidTransaction(storageSpaceInfo.Id, newTransaction, status);
                    }
                }

                partNo += 1;
                SetTransactionDetails(priority, formulary, facility, facilityFormulary, destination, request, item, partNo, orderCount, newTransaction, quantity);

                //ADU Processing variables
                Tuple <bool, bool> admResult = default(Tuple <bool, bool>);
                bool isIgnoredTxn = false, isPartialUpdated = false;

                if (newTransaction.Status != TransactionStatus.Exception &&
                    status != TransactionStatus.Ignored &&
                    priority.IsAdu.GetValueOrDefault(false))
                {
                    admResult = await _aduTransactionManager.ProcessAduTransaction(request, newTransaction, item, priority, facility);

                    isIgnoredTxn     = admResult.Item1;
                    isPartialUpdated = admResult.Item2;

                    //Logging for ADU Processing
                    if (isIgnoredTxn)
                    {
                        _logger.LogInformation(string.Format(CommonConstants.LoggingMessage.ProcessedAdmTransaction, request.RequestId));
                    }
                }

                ConfigureTimeToLive(priority, newTransaction);

                if (status != TransactionStatus.Ignored && !isIgnoredTxn && !isPartialUpdated)
                {
                    newTransaction.TransactionQueueId = await _transactionQueueRepository.CreateTransaction(newTransaction);

                    _logger.LogInformation(string.Format(CommonConstants.LoggingMessage.TransactionCreated, newTransaction.TransactionQueueId, newTransaction.IncomingRequestId));

                    if (newTransaction.Status == TransactionStatus.Interim)
                    {
                        PublishFormularyLocationRequest(newTransaction, headers);
                    }
                }
                else if (!isPartialUpdated)
                {
                    newTransaction.Status             = TransactionStatus.Ignored;
                    newTransaction.TransactionQueueId = await _transactionQueueHistoryRepository.CreateTransaction(newTransaction);

                    _logger.LogInformation(string.Format(CommonConstants.LoggingMessage.IgnoredTransactionCreated, newTransaction.TransactionQueueId, newTransaction.IncomingRequestId));
                }
            }
        }
        private void SetTransactionDetails(TransactionPriority priority, Formulary formulary, Facility facility,
                                           FacilityFormulary facilityFormulary, Destination destination, TransactionRequest incomingRequest,
                                           Item item, int partNo, int orderCount, TransactionQueueModel newTransaction, int quantity)
        {
            var  localNow = DateTime.Now;
            var  utcNow   = DateTime.UtcNow;
            User usr      = new User(UserName.Admin.ToString());

            newTransaction.StatusChangeDT          = localNow;
            newTransaction.StatusChangeUtcDateTime = utcNow;

            if (formulary != null)
            {
                newTransaction.Description = (priority != null && priority.UseInterfaceItemName.GetValueOrDefault()) ? item.ItemName : formulary.Description;
                newTransaction.FormularyId = formulary.FormularyId;
            }
            // Apply ADU Round if Qualifies
            if (quantity > 0 && facility != null && priority != null && destination != null &&
                facilityFormulary != null && (priority.IsAdu != null && (bool)priority.IsAdu) &&
                (facility.AduQtyRounding != null && (bool)facility.AduQtyRounding) &&
                (facilityFormulary.AduQtyRounding != null && (bool)facilityFormulary.AduQtyRounding) &&
                (destination.AduQtyRounding != null && (bool)destination.AduQtyRounding))
            {
                newTransaction.Quantity          = AduQtyRound(quantity);
                newTransaction.QuantityProcessed = newTransaction.Quantity;
                _logger.LogInformation(string.Format(CommonConstants.LoggingMessage.AduQuantity, newTransaction.Quantity, incomingRequest.RequestId));
            }
            else
            {
                newTransaction.Quantity          = quantity;
                newTransaction.QuantityProcessed = newTransaction.Quantity;
            }

            newTransaction.Type    = TransactionType.Pick;
            newTransaction.OrderId = incomingRequest.Order?.OrderNo;
            newTransaction.ItemId  = item.ItemId;

            if (!string.IsNullOrEmpty(item.ComponentStrength))
            {
                newTransaction.Strength = item.ComponentStrength.Trim();
            }

            if (!string.IsNullOrEmpty(item.ComponentStrengthUnits))
            {
                newTransaction.StrengthUnit = item.ComponentStrengthUnits.Trim();
            }

            //set these two to real values for display purposes
            newTransaction.ComponentNumber    = partNo;
            newTransaction.NumberOfComponents = orderCount;

            // Patient info
            SetPatientInfo(newTransaction, incomingRequest);

            newTransaction.FacilityId        = facility.Id;
            newTransaction.IncomingRequestId = incomingRequest.RequestId;

            if (priority != null)
            {
                newTransaction.TranPriorityId = priority.TransactionPriorityId;
            }

            newTransaction.ReceivedDt          = localNow;
            newTransaction.ReceivedUtcDateTime = utcNow;

            if (usr != null)
            {
                newTransaction.RequestedBy = usr.UserName;
            }

            if (!string.IsNullOrEmpty(incomingRequest.Patient?.DeliverToLocation))
            {
                newTransaction.Destination = incomingRequest.Patient.DeliverToLocation.Trim();
            }

            if (!string.IsNullOrEmpty(newTransaction.Exception) &&
                newTransaction.Exception.Length > 80)
            {
                newTransaction.Exception = newTransaction.Exception.Substring(0, 80);
            }

            if (!string.IsNullOrEmpty(item.Concentration))
            {
                newTransaction.Concentration = item.Concentration.Trim();
            }
            if (!string.IsNullOrEmpty(item.TotalDose))
            {
                newTransaction.TotalDose = item.TotalDose.Trim();
            }
            if (!string.IsNullOrEmpty(item.DispenseAmount))
            {
                newTransaction.DispenseAmount = item.DispenseAmount.Trim();
            }
        }