private int UpdateBalance(ItemTransaction it)
    {
        HealthFacilityBalance hb = HealthFacilityBalance.GetHealthFacilityBalance(it.HealthFacilityCode, it.Gtin, it.GtinLot);
        int i = -1;

        if (hb != null)
        {
            hb.StockCount = it.TransactionQtyInBaseUom;
            int qty = (int)(hb.Balance - it.TransactionQtyInBaseUom);
            if (qty > 0)
            {
                WastageTransaction(it, qty);
            }
            hb.Balance = it.TransactionQtyInBaseUom;
            i          = HealthFacilityBalance.Update(hb);
        }
        else
        {
            HealthFacilityBalance hbnew = new HealthFacilityBalance();
            hbnew.HealthFacilityCode = it.HealthFacilityCode;
            hbnew.Gtin       = it.Gtin;
            hbnew.LotNumber  = it.GtinLot;
            hbnew.StockCount = it.TransactionQtyInBaseUom;
            hbnew.Balance    = it.TransactionQtyInBaseUom;
            i = HealthFacilityBalance.Insert(hbnew);
        }
        return(i);
    }
        /// <summary>
        /// Allocate stock
        /// </summary>
        /// <param name="facility">The facility in which to allocate stock</param>
        /// <param name="gtin">The GTIN of the stock to be allocated</param>
        /// <param name="lot">The lot number of stock to be allocated</param>
        /// <param name="qty">The amount of stock to be allocated</param>
        /// <returns>The <see cref="T:GIIS.DataLayer.ItemTransaction"/> representing the allocation</returns>
        public ItemTransaction Allocate(HealthFacility facility, String gtin, String lot, Int32 qty, TransferOrderDetail orderLine, Int32 modifiedBy)
        {
            // Sanity check
            if (facility == null)
            {
                throw new ArgumentNullException("facility");
            }
            else if (String.IsNullOrEmpty(gtin))
            {
                throw new ArgumentNullException("gtin");
            }
            else if (String.IsNullOrEmpty(lot))
            {
                throw new ArgumentNullException("lot");
            }

            // Adjustment type
            TransactionType allocationType = TransactionType.GetTransactionTypeList().FirstOrDefault(o => o.Name == "Allocation");

            if (allocationType == null)
            {
                throw new InvalidOperationException("Cannot find transaction type 'Allocation'");
            }

            // Get current balance and ensure we have enough to do the balance
            var balance = this.GetCurrentBalance(facility, gtin, lot);

            //if (qty > 0 && balance.Balance < qty)
            //    throw new InvalidOperationException(String.Format("Cannot de-allocate more stock than is available (Request: {0},  Available:{1}, GTIN: {2})", qty, balance, ItemLot.GetItemLotByGtin(gtin).ItemObject.Name));
            //else if (qty < 0 && balance.Allocated < -qty)
            //    throw new InvalidOperationException("Cannot de-allocate more stock than is currently allocated");

            // Create an item transaction
            ItemTransaction retVal = new ItemTransaction()
            {
                Gtin                                                              = gtin,
                GtinLot                                                           = lot,
                HealthFacilityCode                                                = facility.Code,
                ModifiedBy                                                        = modifiedBy,
                ModifiedOn                                                        = DateTime.Now,
                RefId                                                             = orderLine != null?orderLine.OrderNum.ToString() : null,
                                                          RefIdNum                = orderLine != null ? orderLine.OrderDetailNum : 0,
                                                          TransactionDate         = DateTime.Now,
                                                          TransactionQtyInBaseUom = qty,
                                                          TransactionTypeId       = allocationType.Id
            };

            // Update the balance
            //balance.Balance -= qty;
            balance.Allocated += qty;

            // Save
            HealthFacilityBalance.Update(balance);
            retVal.Id = ItemTransaction.Insert(retVal);

            return(retVal);
        }
        /// <summary>
        /// Performs a stock count for the specified <paramref name="gtin"/> at <paramref name="facility"/>
        /// </summary>
        /// <param name="facility">The facility in which the count occurred</param>
        /// <param name="gtin">The GTIN of the item being counted</param>
        /// <param name="lot">The lot number of the item being counted</param>
        /// <param name="count">The count of items</param>
        /// <returns>The <see cref="T:GIIS.DataLayer.ItemTransaction"/> representing the count</returns>
        public ItemTransaction StockCount(HealthFacility facility, String gtin, String lot, UInt32 count, Int32 modifiedBy, DateTime date)
        {
            // Validate
            if (facility == null)
            {
                throw new ArgumentNullException("facility");
            }
            else if (String.IsNullOrEmpty(gtin))
            {
                throw new ArgumentNullException("gtin");
            }
            else if (String.IsNullOrEmpty(lot))
            {
                throw new ArgumentNullException("lot");
            }

            // Stock Count
            TransactionType stockCountType = TransactionType.GetTransactionTypeList().FirstOrDefault(o => o.Name == "Stock Count");

            if (stockCountType == null)
            {
                throw new InvalidOperationException("Cannot find transaction type 'Stock Count'");
            }

            // Balance
            var balance = this.GetCurrentBalance(facility, gtin, lot);

            // Now we want to create transaction for count operation
            ItemTransaction retVal = new ItemTransaction()
            {
                Gtin                    = gtin,
                GtinLot                 = lot,
                HealthFacilityCode      = facility.Code,
                ModifiedBy              = modifiedBy,
                ModifiedOn              = DateTime.Now,
                TransactionDate         = date,
                TransactionQtyInBaseUom = count,
                TransactionTypeId       = stockCountType.Id
            };

            // Overwrite the values
            int qty = (int)(balance.Balance - count);

            if (qty > 0)
            {
                Adjust(facility, gtin, lot, qty, AdjustmentReason.GetAdjustmentReasonById(99), modifiedBy, date);
            }
            balance.StockCount = balance.Balance = count;

            // Save
            HealthFacilityBalance.Update(balance);
            int i = ItemTransaction.Insert(retVal);

            return(ItemTransaction.GetItemTransactionById(i));
        }
    private int UpdateBalance(ItemTransaction it, int qty)
    {
        HealthFacilityBalance hb = HealthFacilityBalance.GetHealthFacilityBalance(it.HealthFacilityCode, it.Gtin, it.GtinLot);
        int i = -1;

        if (hb != null)
        {
            hb.StockCount += qty; //??
            hb.Balance    += qty;
            WastageTransaction(it, qty);
            i = HealthFacilityBalance.Update(hb);
        }
        return(i);
    }
 /// <summary>
 /// Performs rollback of stock transaction for a vaccination event
 /// </summary>
 /// <param name="facility">The healthfacility where the vaccination event happened</param>
 /// <param name="vaccineLotId">The vaccine lot that was used in the vaccination event</param>
 public int ClearBalance(HealthFacility facility, int vaccineLotId)
 {
     if (vaccineLotId > 0)
     {
         ItemLot il = ItemLot.GetItemLotById(vaccineLotId);
         HealthFacilityBalance hb = HealthFacilityBalance.GetHealthFacilityBalance(facility.Code, il.Gtin, il.LotNumber);
         if (hb != null)
         {
             hb.Used    -= 1;
             hb.Balance += 1;
             int i = HealthFacilityBalance.Update(hb);
             return(i);
         }
     }
     return(-1);
 }
Пример #6
0
    private int UpdateBalance(ItemTransaction it, int qty)
    {
        HealthFacilityBalance hb = HealthFacilityBalance.GetHealthFacilityBalance(it.HealthFacilityCode, it.Gtin, it.GtinLot);
        int i = -1;

        if (hb != null)
        {
            if (it.AdjustmentObject.Positive)
            {
                hb.Balance += qty;
            }
            else
            {
                hb.Balance -= qty;
                hb.Wasted  += qty;
            }
            i = HealthFacilityBalance.Update(hb);
        }
        return(i);
    }
Пример #7
0
        /// <summary>
        /// Initialize the test data
        /// </summary>
        public static void InitializeTestDataset()
        {
            /// Transaction type 999 = ID
            var transactionTypes = TransactionType.GetTransactionTypeList();

            if (!transactionTypes.Exists(o => o.Name == "Allocation"))
            {
                TransactionType.Insert(new TransactionType()
                {
                    Name = "Allocation"
                });
            }
            if (!transactionTypes.Exists(o => o.Name == "Transfer"))
            {
                TransactionType.Insert(new TransactionType()
                {
                    Name = "Transfer"
                });
            }


            // GTIN 12345 - PHARMACO OPV
            if (ItemManufacturer.GetItemManufacturerByGtin(GTIN_UNDER_TEST) == null)
            {
                // Item Category 999 = Vaccine
                if (ItemCategory.GetItemCategoryById(VACCINE_CATEGORY_ID) == null)
                {
                    VACCINE_CATEGORY_ID = ItemCategory.Insert(new ItemCategory()
                    {
                        Id         = VACCINE_CATEGORY_ID,
                        Code       = "VACCINE",
                        IsActive   = true,
                        ModifiedBy = 1,
                        ModifiedOn = DateTime.Now,
                        Name       = "Vaccine"
                    });
                }

                // Item 999 - OPV
                if (Item.GetItemById(OPV_ITEM_ID) == null)
                {
                    OPV_ITEM_ID = Item.Insert(new Item()
                    {
                        Code           = "OPV",
                        EntryDate      = DateTime.Now,
                        Id             = OPV_ITEM_ID,
                        ItemCategoryId = VACCINE_CATEGORY_ID,
                        IsActive       = true,
                        ModifiedBy     = 1,
                        ModifiedOn     = DateTime.Now,
                        Name           = "OPV"
                    });
                }

                // Unit of Measure
                if (Uom.GetUomById(DOSE_UOM_ID) == null)
                {
                    DOSE_UOM_ID = Uom.Insert(new Uom()
                    {
                        Id   = DOSE_UOM_ID,
                        Name = "DOSE"
                    });
                }

                // Manufacturer 999 - PHARMACO
                if (Manufacturer.GetManufacturerById(PHARMACO_MANUFACTURER_ID) == null)
                {
                    PHARMACO_MANUFACTURER_ID = Manufacturer.Insert(new Manufacturer()
                    {
                        Id         = PHARMACO_MANUFACTURER_ID,
                        Code       = "PHX",
                        IsActive   = true,
                        ModifiedBy = 1,
                        ModifiedOn = DateTime.Now,
                        Name       = "PHARMACO INC."
                    });
                }

                ItemManufacturer.Insert(new ItemManufacturer()
                {
                    Alt1QtyPer = 20,
                    BaseUom    = "DOSE",
                    BaseUomChildPerBaseUomParent = 10,
                    Gtin           = GTIN_UNDER_TEST,
                    IsActive       = true,
                    ItemId         = OPV_ITEM_ID,
                    ManufacturerId = PHARMACO_MANUFACTURER_ID,
                    ModifiedBy     = 1,
                    ModifiedOn     = DateTime.Now,
                    Price          = 9.99,
                    StorageSpace   = 1,
                    Alt1Uom        = "DOSE",
                    Alt2QtyPer     = 30,
                    Alt2Uom        = "DOSE"
                });
            }

            if (ItemLot.GetItemLotByGtin(GTIN_UNDER_TEST) == null)
            {
                // Item 999 - OPV
                if (Item.GetItemById(OPV_ITEM_ID) == null)
                {
                    OPV_ITEM_ID = Item.Insert(new Item()
                    {
                        Code           = "OPV",
                        EntryDate      = DateTime.Now,
                        Id             = OPV_ITEM_ID,
                        ItemCategoryId = VACCINE_CATEGORY_ID,
                        IsActive       = true,
                        ModifiedBy     = 1,
                        ModifiedOn     = DateTime.Now,
                        Name           = "OPV"
                    });
                }

                ItemLot.Insert(new ItemLot()
                {
                    ExpireDate = DateTime.Now.AddDays(10),
                    Gtin       = GTIN_UNDER_TEST,
                    ItemId     = OPV_ITEM_ID,
                    LotNumber  = GTIN_LOT_USE_FIRST
                });

                // Item Lot 2 - Will be more stock and expires later
                ItemLot.Insert(new ItemLot()
                {
                    ExpireDate = DateTime.Now.AddDays(40),
                    Gtin       = GTIN_UNDER_TEST,
                    ItemId     = OPV_ITEM_ID,
                    LotNumber  = GTIN_LOT_USE_LAST
                });

                // Item Lot 3 - Will trigger low stock
                ItemLot.Insert(new ItemLot()
                {
                    ExpireDate = DateTime.Now.AddDays(80),
                    Gtin       = GTIN_UNDER_TEST,
                    ItemId     = OPV_ITEM_ID,
                    LotNumber  = GTIN_LOT_LOW_BAL
                });
            }

            // Type 3 = DISTRICT
            if (HealthFacilityType.GetHealthFacilityTypeById(6) == null)
            {
                HealthFacilityType.Insert(new HealthFacilityType()
                {
                    Id         = 3,
                    Code       = "DISTRICT",
                    IsActive   = true,
                    ModifiedBy = 1,
                    ModifiedOn = DateTime.Now,
                    Name       = "DISTRICT LEVEL"
                });
            }

            // Type 6 = SDP
            if (HealthFacilityType.GetHealthFacilityTypeById(6) == null)
            {
                HealthFacilityType.Insert(new HealthFacilityType()
                {
                    Id         = 6,
                    Code       = "SDP",
                    IsActive   = true,
                    ModifiedBy = 1,
                    ModifiedOn = DateTime.Now,
                    Name       = "SDP"
                });
            }

            // HF888 = DISTRICT
            if (HealthFacility.GetHealthFacilityByCode("HF888") == null)
            {
                HealthFacility.Insert(new HealthFacility()
                {
                    Id   = 888,
                    Code = "HF888",
                    ColdStorageCapacity = 1000,
                    IsActive            = true,
                    Leaf             = false,
                    ParentId         = HealthFacility.GetHealthFacilityByParentId(0)[0].Id,
                    TopLevel         = false,
                    TypeId           = 3,
                    VaccinationPoint = false,
                    VaccineStore     = true,
                    ModifiedBy       = 1,
                    ModifiedOn       = DateTime.Now
                });
            }

            // GIVE HEALTH FACILITY SOME BALANCE
            var hf888Balances = HealthFacilityBalance.GetHealthFacilityBalanceByHealthFacilityCode("HF888");
            HealthFacilityBalance useFirst = hf888Balances.Find(o => o.Gtin == GTIN_UNDER_TEST && o.LotNumber == GTIN_LOT_USE_FIRST),
                                  useLast  = hf888Balances.Find(o => o.Gtin == GTIN_UNDER_TEST && o.LotNumber == GTIN_LOT_USE_LAST),
                                  lowStock = hf888Balances.Find(o => o.Gtin == GTIN_UNDER_TEST && o.LotNumber == GTIN_LOT_LOW_BAL);

            if (useFirst == null)
            {
                useFirst = new HealthFacilityBalance()
                {
                    Allocated          = 0,
                    Balance            = 500,
                    Distributed        = 0,
                    Gtin               = GTIN_UNDER_TEST,
                    HealthFacilityCode = "HF888",
                    LotNumber          = GTIN_LOT_USE_FIRST,
                    Received           = 0,
                    StockCount         = 500,
                    Used               = 0,
                    Wasted             = 0
                };
                hf888Balances.Add(useFirst);
                HealthFacilityBalance.Insert(useFirst);
            }
            else
            {
                useFirst.Balance    = 500;
                useFirst.StockCount = 500;
                HealthFacilityBalance.Update(useFirst);
            }

            if (useLast == null)
            {
                useLast = new HealthFacilityBalance()
                {
                    Allocated          = 0,
                    Balance            = 1000,
                    Distributed        = 0,
                    Gtin               = GTIN_UNDER_TEST,
                    HealthFacilityCode = "HF888",
                    LotNumber          = GTIN_LOT_USE_LAST,
                    Received           = 0,
                    StockCount         = 1000,
                    Used               = 0,
                    Wasted             = 0
                };
                hf888Balances.Add(useLast);
                HealthFacilityBalance.Insert(useLast);
            }
            else
            {
                useLast.Balance    = 1000;
                useLast.StockCount = 1000;
                HealthFacilityBalance.Update(useLast);
            }

            if (lowStock == null)
            {
                lowStock = new HealthFacilityBalance()
                {
                    Allocated          = 0,
                    Balance            = 10,
                    Distributed        = 0,
                    Gtin               = GTIN_UNDER_TEST,
                    HealthFacilityCode = "HF888",
                    LotNumber          = GTIN_LOT_LOW_BAL,
                    Received           = 0,
                    StockCount         = 10,
                    Used               = 0,
                    Wasted             = 0
                };
                hf888Balances.Add(lowStock);
                HealthFacilityBalance.Insert(lowStock);
            }
            else
            {
                useLast.Balance    = 10;
                useLast.StockCount = 10;
                HealthFacilityBalance.Update(lowStock);
            }

            // HF999 = SDP
            if (HealthFacility.GetHealthFacilityByCode("HF999") == null)
            {
                HealthFacility.Insert(new HealthFacility()
                {
                    Id   = 999,
                    Code = "HF999",
                    ColdStorageCapacity = 100,
                    IsActive            = true,
                    Leaf             = true,
                    ParentId         = HealthFacility.GetHealthFacilityByCode("HF888").Id,
                    TopLevel         = false,
                    TypeId           = 6,
                    VaccinationPoint = true,
                    VaccineStore     = true,
                    ModifiedOn       = DateTime.Now,
                    ModifiedBy       = 1
                });
            }
        }
        /// <summary>
        /// Make an adjustment
        /// </summary>
        /// <param name="facility">The facility in which the adjustment is being made</param>
        /// <param name="gtin">The GTIN of the stock item being adjusted</param>
        /// <param name="lot">The lot number of the stock being adjusted</param>
        /// <param name="qty">The amount of the adjustment</param>
        /// <param name="reason">The reason for the adjustment</param>
        /// <returns>The <see cref="T:GIIS.DataLayer.ItemTransaction"/> representing the transaction created</returns>
        /// <remarks>This method updates the ItemTransaction and HealthFacility Balances</remarks>
        public ItemTransaction Adjust(HealthFacility facility, String gtin, String lot, Int32 qty, AdjustmentReason reason, Int32 modifiedBy, DateTime date)
        {
            if (facility == null)
            {
                throw new ArgumentNullException("facility");
            }
            else if (String.IsNullOrEmpty(gtin))
            {
                throw new ArgumentNullException("gtin");
            }

            // Adjustment type
            TransactionType adjustmentType = TransactionType.GetTransactionTypeList().FirstOrDefault(o => o.Name == "Adjustment");

            if (adjustmentType == null)
            {
                throw new InvalidOperationException("Cannot find transaction type 'Adjustment'");
            }

            var balance = this.GetCurrentBalance(facility, gtin, lot);

            // Sanity check, is there a balance of this?
            //if (qty < 0 && -qty > balance.Balance)
            //    throw new InvalidOperationException("Quantity is a negative adjustment on a balance which exceeds the current balance");
            int quantity;

            if (reason.Positive)
            {
                quantity = qty;
            }
            else
            {
                quantity = -qty;
            }
            // Create the item transaction
            ItemTransaction retVal = new ItemTransaction()
            {
                ModifiedBy              = modifiedBy,
                AdjustmentId            = reason.Id,
                Gtin                    = gtin,
                GtinLot                 = lot,
                HealthFacilityCode      = facility.Code,
                ModifiedOn              = DateTime.Now,
                TransactionDate         = date,
                TransactionQtyInBaseUom = quantity,
                TransactionTypeId       = adjustmentType.Id
            };

            // Adjust the balance
            // An adjustment reason can be positive - results in increased balance
            if (reason.Id != 99)
            {
                if (reason.Positive)
                {
                    balance.Balance += qty;
                }
                else
                {
                    balance.Balance -= qty;
                    balance.Wasted  += qty;
                }
            }
            // Adjust the balances of other reasons
            //if(adjustmentType != null)
            //{
            //    switch(adjustmentType.Name)
            //    {
            //        case "Adjustments":
            //            balance.Wasted += -qty;
            //            break;
            //    }
            //}

            // Save the balances
            HealthFacilityBalance.Update(balance);
            int i = ItemTransaction.Insert(retVal);

            return(ItemTransaction.GetItemTransactionById(i));
        }
        /// <summary>
        /// Performs stock transaction for a vaccination event
        /// </summary>
        /// <param name="facility">The facility in which the vaccination event occurred</param>
        /// <param name="vaccination">The vaccination event</param>
        /// <returns>The <see cref="T:GIIS.DataLayer.ItemTransaction"/> representing the transfer</returns>
        public ItemTransaction Vaccinate(HealthFacility facility, VaccinationEvent vaccination)
        {
            // Vaccination not given = no transaction
            if (!vaccination.VaccinationStatus)
            {
                return(null);
            }

            List <ItemLot> lots = new List <ItemLot>();

            // Verify
            if (facility == null)
            {
                throw new ArgumentNullException("facility");
            }
            else if (vaccination == null)
            {
                throw new ArgumentNullException("vaccination");
            }
            else if (String.IsNullOrEmpty(vaccination.VaccineLot))
            {
                ItemManufacturer     gtin = ItemManufacturer.GetItemManufacturerByItem(vaccination.Dose.ScheduledVaccination.ItemId);
                OrderManagementLogic oml  = new OrderManagementLogic();
                lots.Add(oml.GetOldestLot(facility, gtin.Gtin));
            }

            //throw new ArgumentException("Vaccination event missing lot#", "vaccination");

            // Item lot that was used
            if (lots.Count == 0)
            {
                lots.Add(ItemLot.GetItemLotById(vaccination.VaccineLotId));
            }
            //lots.Add(ItemLot.GetItemLotByLotNumber(vaccination.VaccineLot));
            if (lots.Count == 0)
            {
                return(null);
            }


            // throw new InvalidOperationException("Cannot find the specified ItemLot relation (GTIN)");

            // Transaction type
            TransactionType vaccinationType = TransactionType.GetTransactionTypeList().FirstOrDefault(o => o.Name == "Vaccination");

            if (vaccinationType == null)
            {
                throw new InvalidOperationException("Cannot find transaction type 'Vaccination'");
            }

            // Return value
            ItemTransaction retVal = null;

            // Iterate through lots
            for (int i = 0; i < lots.Count; i++)
            {
                var lot = lots[i];

                // Get balance
                HealthFacilityBalance balance = this.GetCurrentBalance(facility, lot.Gtin, lot.LotNumber);
                //if (balance.Balance < 1)
                //    throw new InvalidOperationException("Insufficient doses to register vaccination event");

                // Create a transaction
#if XAMARIN
#else
#endif
                ItemTransaction itl = new ItemTransaction()
                {
                    Gtin                    = lot.Gtin,
                    GtinLot                 = lot.LotNumber,
                    HealthFacilityCode      = facility.Code,
                    ModifiedBy              = vaccination.ModifiedBy,
                    ModifiedOn              = vaccination.ModifiedOn,
                    RefIdNum                = vaccination.Id,
                    TransactionDate         = vaccination.VaccinationDate,
                    TransactionQtyInBaseUom = -1,
                    TransactionTypeId       = vaccinationType.Id
                };
                if (String.IsNullOrEmpty(vaccination.VaccineLot))
                {
                    vaccination.VaccineLotId = lot.Id;
                    VaccinationEvent.Update(vaccination);
                }

                // Update facility balances
                balance.Balance -= 1;
                balance.Used    += 1;

                // Now save
                HealthFacilityBalance.Update(balance);
                itl.Id = ItemTransaction.Insert(itl);

                if (retVal == null)
                {
                    retVal = itl;
                }

                // Linked or kitted items
                var lotGtinItem = ItemManufacturer.GetItemManufacturerByGtin(lot.Gtin);
                foreach (var im in lotGtinItem.KitItems)
                {
                    lots.Add(new OrderManagementLogic().GetOldestLot(facility, im.Gtin));
                }
            }

            return(retVal);
        }
        /// <summary>
        /// Transfers stock from facility <paramref name="from"/> to facility <paramref name="to"/>
        /// </summary>
        /// <param name="from">The facility from which stock is being transferred</param>
        /// <param name="to">The facility to which stock is being transferred</param>
        /// <param name="gtin">The GTIN of the stock being transfered</param>
        /// <param name="lot">The lot of the stock being transferred</param>
        /// <param name="orderDetail">The order detail which informed this transfer</param>
        /// <param name="qty">The quantity of stock to be transferred</param>
        /// <returns>The <see cref="T:GIIS.DataLayer.ItemTransaction"/> representing the transfers </returns>
        public List <ItemTransaction> Transfer(HealthFacility from, HealthFacility to, String gtin, String lot, TransferOrderDetail orderDetail, Int32 qty, Int32 modifiedBy)
        {
            // Validate parameters
            if (from == null)
            {
                throw new ArgumentNullException("from");
            }
            else if (to == null)
            {
                throw new ArgumentNullException("to");
            }
            else if (String.IsNullOrEmpty(gtin))
            {
                throw new ArgumentNullException("gtin");
            }
            else if (String.IsNullOrEmpty(lot))
            {
                throw new ArgumentNullException("lot");
            }

            // Transfer type
            TransactionType transferType = TransactionType.GetTransactionTypeList().FirstOrDefault(o => o.Name == "Transfer");

            if (transferType == null)
            {
                throw new InvalidOperationException("Cannot find transaction type 'Transfer'");
            }

            // Lookup the current balances in both facilities
            HealthFacilityBalance fromBalance = this.GetCurrentBalance(from, gtin, lot),
                                  toBalance   = this.GetCurrentBalance(to, gtin, lot);

            // Validate the fromBalance has sufficient quantity to transfer
            //if (fromBalance.Balance < qty)
            //    throw new InvalidOperationException("Insufficient quantity in the 'from' facility to perform transfer");

            // Two ItemTransactions
            ItemTransaction fromTransaction = new ItemTransaction()
            {
                Gtin                                                              = gtin,
                GtinLot                                                           = lot,
                HealthFacilityCode                                                = from.Code,
                ModifiedBy                                                        = modifiedBy,
                ModifiedOn                                                        = DateTime.Now,
                RefId                                                             = orderDetail != null?orderDetail.OrderNum.ToString() : null,
                                                          RefIdNum                = orderDetail != null ? orderDetail.OrderDetailNum : 0,
                                                          TransactionDate         = DateTime.Now,
                                                          TransactionQtyInBaseUom = -qty, // transfer out
                                                          TransactionTypeId       = transferType.Id
            },
                            toTrasnaction = new ItemTransaction()
            {
                Gtin                                                              = gtin,
                GtinLot                                                           = lot,
                HealthFacilityCode                                                = to.Code,
                ModifiedBy                                                        = modifiedBy,
                ModifiedOn                                                        = DateTime.Now,
                RefId                                                             = orderDetail != null?orderDetail.OrderNum.ToString() : null,
                                                          RefIdNum                = orderDetail != null ? orderDetail.OrderDetailNum : 0,
                                                          TransactionDate         = DateTime.Now,
                                                          TransactionQtyInBaseUom = qty, // transfer in
                                                          TransactionTypeId       = transferType.Id
            };

            // Update balances
            fromBalance.Balance     -= qty;
            toBalance.Balance       += qty;
            toBalance.Received      += qty;
            fromBalance.Distributed += qty;

            // Save
            HealthFacilityBalance.Update(fromBalance);
            HealthFacilityBalance.Update(toBalance);
            fromTransaction.Id = ItemTransaction.Insert(fromTransaction);
            toTrasnaction.Id   = ItemTransaction.Insert(toTrasnaction);

            // Return
            return(new List <ItemTransaction>()
            {
                fromTransaction, toTrasnaction
            });
        }