/// <summary author="Richard Carroll" created="2019/01/30">
        /// Passes information from the Presentation Layer to the Data Access
        /// Layer and returns the result of the Insertion attempt.
        /// </summary>
        public bool CreateInternalOrder(InternalOrder itemOrder, List <VMInternalOrderLine> lines)
        {
            bool result = false;

            try
            {
                if (!itemOrder.isValid())
                {
                    throw new ArgumentException("Data entered for this order is invalid\n " +
                                                itemOrder.ToString());
                }
                foreach (var line in lines)
                {
                    if (!line.isValid())
                    {
                        throw new ArgumentException("Data entered for this order is invalid\n" +
                                                    line.ToString());
                    }
                }
                result = (_itemOrderAccessor.InsertItemOrder(itemOrder, lines) > 0);
            }
            catch (Exception ex)
            {
                ExceptionLogManager.getInstance().LogException(ex);
                throw ex;
            }

            return(result);
        }
        private async Task <bool> ValidateInstrumentAsync(InternalOrder internalOrder)
        {
            Instrument instrument = await _instrumentService.TryGetByAssetPairIdAsync(internalOrder.AssetPairId);

            string error = null;

            if (instrument == null)
            {
                error = Errors.AssetPairNotSupported;
            }
            else if (Math.Round(internalOrder.Volume, instrument.VolumeAccuracy) < instrument.MinVolume)
            {
                error = Errors.TooSmallVolume;
            }
            else if (Math.Abs(internalOrder.Volume) % 1 * (decimal)Math.Pow(10, instrument.VolumeAccuracy) % 1 != 0)
            {
                error = Errors.InvalidVolume;
            }

            if (!string.IsNullOrEmpty(error))
            {
                internalOrder.Status       = InternalOrderStatus.Rejected;
                internalOrder.RejectReason = error;

                await _internalOrderRepository.UpdateAsync(internalOrder);

                return(false);
            }

            return(true);
        }
Exemple #3
0
        public void AddItemOrderTestValidInput()
        {
            internalOrder = new InternalOrder()
            {
                InternalOrderID = 8000, EmployeeID = 100000, DepartmentID = "Events",
                Description     = "Food Order... maybe", OrderComplete = false, DateOrdered = DateTime.Now
            };
            _internalOrderLine = new VMInternalOrderLine()
            {
                ItemID      = 100000, OrderQty = 100,
                QtyReceived = 100
            };
            lines = new List <VMInternalOrderLine>();
            lines.Add(_internalOrderLine);
            _internalOrderManager.CreateInternalOrder(internalOrder, lines);

            retrievedOrders = _internalOrderManager.RetrieveAllInternalOrders();
            retrievedLines  = _internalOrderManager.RetrieveOrderLinesByID(internalOrder.InternalOrderID);

            Assert.IsNotNull(retrievedOrders.Find(o => o.InternalOrderID == internalOrder.InternalOrderID &&
                                                  o.EmployeeID == internalOrder.EmployeeID && o.DepartmentID == internalOrder.DepartmentID &&
                                                  o.Description == internalOrder.Description && o.OrderComplete == internalOrder.OrderComplete &&
                                                  o.DateOrdered == internalOrder.DateOrdered));
            Assert.IsNotNull(retrievedLines.Find(l => l.ItemID == _internalOrderLine.ItemID &&
                                                 l.OrderQty == _internalOrderLine.OrderQty && l.QtyReceived ==
                                                 _internalOrderLine.QtyReceived));
        }
        /// <summary>
        /// Richard Carroll
        /// Created: 2019/01/30
        ///
        /// Pulls Order Data from the fields and Line data from
        /// the temporary list to call the insert method in the Logic Layer
        /// </summary>
        private void BtnSave_Click(object sender, RoutedEventArgs e)
        {
            if (checkOrderFields() && lines.Count != 0)
            {
                InternalOrder internalOrder = new InternalOrder();
                internalOrder.EmployeeID    = int.Parse(txtEmployeeID.Text);
                internalOrder.OrderComplete = ((string)cboOrderComplete.SelectedItem == "Yes");
                internalOrder.DateOrdered   = dtpDateOrdered.DisplayDate;
                internalOrder.Description   = txtDescription.Text;
                internalOrder.DepartmentID  = txtDepartmentID.Text;

                try
                {
                    _internalOrderManager.CreateInternalOrder(internalOrder, lines);
                    MessageBox.Show("Order Submitted Successfully");
                    this.DialogResult = true;
                    this.Close();
                }
                catch (Exception ex)
                {
                    MessageBox.Show("Failed to Insert Internal order records: \n" +
                                    ex.Message);
                }
            }
        }
        private async Task <bool> ReserveFundsAsync(InternalOrder internalOrder)
        {
            Instrument instrument = await _instrumentService.TryGetByAssetPairIdAsync(internalOrder.AssetPairId);

            AssetPair assetPair = await _assetsServiceWithCache.TryGetAssetPairAsync(instrument.AssetPairId);

            string  assetId;
            decimal amount;

            if (internalOrder.Type == LimitOrderType.Sell)
            {
                assetId = assetPair.BaseAssetId;
                amount  = internalOrder.Volume;
            }
            else
            {
                Asset asset = await _assetsServiceWithCache.TryGetAssetAsync(assetPair.QuotingAssetId);

                assetId = assetPair.QuotingAssetId;
                amount  = (internalOrder.Volume * internalOrder.Price).TruncateDecimalPlaces(asset.Accuracy, true);
            }

            _log.InfoWithDetails("Reserve funds for internal trade",
                                 new { OrderId = internalOrder.Id, Asset = assetId, Amount = amount });

            string error = null;

            string walletId = await _settingsService.GetWalletIdAsync();

            try
            {
                await _lykkeExchangeService.TransferAsync(internalOrder.WalletId, walletId, assetId, amount);
            }
            catch (NotEnoughFundsException)
            {
                error = Errors.NotEnoughFunds;
            }
            catch (Exception)
            {
                error = "An unexpected error occurred during reserving funds";
            }

            if (!string.IsNullOrEmpty(error))
            {
                internalOrder.Status       = InternalOrderStatus.Rejected;
                internalOrder.RejectReason = error;

                await _internalOrderRepository.UpdateAsync(internalOrder);

                return(false);
            }

            internalOrder.Status = InternalOrderStatus.Reserved;
            await _internalOrderRepository.UpdateAsync(internalOrder);

            return(true);
        }
        public async Task <string> CreateOrderAsync(string walletId, string assetPairId, LimitOrderType type,
                                                    decimal price, decimal volume, bool fullExecution)
        {
            var internalOrder = new InternalOrder(walletId, assetPairId, type, price, volume, fullExecution);

            await _internalOrderRepository.InsertAsync(internalOrder);

            return(internalOrder.Id);
        }
        public static async void ReplaceOrderTimeOnInternalOrder()
        {
            // create internal order
            InternalOrder internalOrder;

            using (var dbContext = new EfTestDbContext()) {
                var repo = new InternalOrderRepository(dbContext);
                var seq  = await repo.NextOrderNumber();

                internalOrder = new InternalOrder("W-{seq}");

                internalOrder.SetTime(new OrderTime("Test"));
                await repo.Update(internalOrder);

                await repo.SaveAsync();

                Debug.Assert(internalOrder.ID != Guid.Empty);
                Debug.Assert(null != internalOrder.OrderTimeID);
            }

            // replace order time
            Guid previousOrderTimeId;

            using (var dbContext = new EfTestDbContext()) {
                var repo = new InternalOrderRepository(dbContext);
                // get untracked InternalOrder
                var order = await dbContext.InternalOrders.Include(x => x.OrderTime).SingleAsync(x => x.ID == internalOrder.ID);

                previousOrderTimeId = order.OrderTime.ID;

                order.SetTime(new OrderTime("Test 1234"));

                Console.WriteLine($"Previous order time id {previousOrderTimeId}");
                Console.WriteLine($"Current order time id {order.OrderTime.ID}");

                await repo.Update(order);

                await Task.Delay(1000); // for sensitive logging to settle

                Console.WriteLine($"-- Before save changes --");
                await repo.SaveAsync();

                Console.WriteLine($"Current order time id after save {order.OrderTime.ID}");
            }

            // check if OrderTime was deleted
            using (var dbContext = new EfTestDbContext()) {
                var repo  = new InternalOrderRepository(dbContext);
                var order = repo.Get(internalOrder.ID);

                Debug.Assert(false == dbContext.OrderTimes.Any(x => x.ID == previousOrderTimeId), "OrderTime is still present");
                Debug.Assert(null != order.OrderTime);
                Debug.Assert("Test 1234" == order.OrderTime.Display);
            }
        }
Exemple #8
0
        public async Task <OrderModel> LimitOrderStatusAsync(string orderId)
        {
            InternalOrder internalOrder = await _internalOrderService.GetByIdAsync(orderId);

            if (internalOrder == null)
            {
                throw new ValidationApiException(HttpStatusCode.NotFound, "Order not found");
            }

            return(Mapper.Map <OrderModel>(internalOrder));
        }
Exemple #9
0
        public async Task InsertAsync(InternalOrder internalOrder)
        {
            var entity =
                new InternalOrderEntity(GetPartitionKey(internalOrder.CreatedDate), GetRowKey(internalOrder.Id));

            Mapper.Map(internalOrder, entity);

            await _storage.InsertAsync(entity);

            AzureIndex index = new AzureIndex(GetIndexPartitionKey(internalOrder.Id), GetIndexRowKey(internalOrder.Id),
                                              entity);

            await _indicesStorage.InsertAsync(index);
        }
        private async Task <bool> TransferFundsAsync(InternalOrder internalOrder)
        {
            if (internalOrder.ExecutedVolume == null || internalOrder.ExecutedPrice == null)
            {
                throw new InvalidOperationException("The executed volume and price not specified");
            }

            Instrument instrument = await _instrumentService.TryGetByAssetPairIdAsync(internalOrder.AssetPairId);

            AssetPair assetPair = await _assetsServiceWithCache.TryGetAssetPairAsync(instrument.AssetPairId);

            string  assetId;
            decimal amount;

            if (internalOrder.Type == LimitOrderType.Sell)
            {
                Asset asset = await _assetsServiceWithCache.TryGetAssetAsync(assetPair.QuotingAssetId);

                assetId = assetPair.QuotingAssetId;
                amount  = (internalOrder.ExecutedVolume.Value * internalOrder.ExecutedPrice.Value)
                          .TruncateDecimalPlaces(asset.Accuracy, true);
            }
            else
            {
                assetId = assetPair.BaseAssetId;
                amount  = internalOrder.ExecutedVolume.Value;
            }

            _log.InfoWithDetails("Transfer funds according internal trade",
                                 new { OrderId = internalOrder.Id, Asset = assetId, Amount = amount });

            string walletId = await _settingsService.GetWalletIdAsync();

            try
            {
                await _lykkeExchangeService.TransferAsync(walletId, internalOrder.WalletId, assetId, amount);
            }
            catch (Exception exception)
            {
                _log.ErrorWithDetails(exception, "Can not transfer funds to destination wallet", internalOrder);

                return(false);
            }

            internalOrder.Status = InternalOrderStatus.Transferred;
            await _internalOrderRepository.UpdateAsync(internalOrder);

            return(true);
        }
        private async Task <bool> TransferRemainingFundsAsync(InternalOrder internalOrder)
        {
            if (internalOrder.ExecutedVolume == null || internalOrder.ExecutedPrice == null)
            {
                throw new InvalidOperationException("The executed volume and price not specified");
            }

            if (internalOrder.Type != LimitOrderType.Buy)
            {
                return(true);
            }

            Instrument instrument = await _instrumentService.TryGetByAssetPairIdAsync(internalOrder.AssetPairId);

            AssetPair assetPair = await _assetsServiceWithCache.TryGetAssetPairAsync(instrument.AssetPairId);

            Asset asset = await _assetsServiceWithCache.TryGetAssetAsync(assetPair.QuotingAssetId);

            decimal originalAmount = internalOrder.Volume * internalOrder.Price;

            decimal executedAmount = (internalOrder.ExecutedVolume.Value * internalOrder.ExecutedPrice.Value)
                                     .TruncateDecimalPlaces(asset.Accuracy, true);

            decimal amount = originalAmount - executedAmount;

            amount = Math.Round(amount, asset.Accuracy);

            if (amount > 0)
            {
                _log.InfoWithDetails("Transfer remaining funds according internal trade",
                                     new { OrderId = internalOrder.Id, Asset = asset.Id, Amount = amount });

                string walletId = await _settingsService.GetWalletIdAsync();

                try
                {
                    await _lykkeExchangeService.TransferAsync(walletId, internalOrder.WalletId, asset.Id, amount);
                }
                catch (Exception exception)
                {
                    _log.ErrorWithDetails(exception, "Can not transfer remaining funds to destination wallet",
                                          internalOrder);

                    return(false);
                }
            }

            return(true);
        }
Exemple #12
0
        public async Task UpdateAsync(InternalOrder internalOrder)
        {
            AzureIndex index = await _indicesStorage.GetDataAsync(GetIndexPartitionKey(internalOrder.Id),
                                                                  GetIndexRowKey(internalOrder.Id));

            if (index == null)
            {
                throw new EntityNotFoundException();
            }

            InternalOrderEntity entity = await _storage.GetDataAsync(index);

            Mapper.Map(internalOrder, entity);

            await _storage.InsertOrReplaceAsync(entity);
        }
        /// <summary>
        /// Richard Carroll
        /// Created: 2019/01/30
        ///
        /// This Method inserts Order Data into the database
        /// and returns the result to the
        /// Logic Layer.
        /// </summary>
        public int InsertItemOrder(InternalOrder internalOrder, List <VMInternalOrderLine> lines)
        {
            int rowsAffected = 0;

            var cmdText1 = "sp_insert_internal_order";
            var cmdText2 = "sp_insert_internal_order_line";

            try
            {
                using (TransactionScope scope = new TransactionScope())
                {
                    using (var conn = DBConnection.GetDbConnection())
                    {
                        conn.Open();

                        var cmd1 = new SqlCommand(cmdText1, conn);
                        cmd1.CommandType = CommandType.StoredProcedure;
                        cmd1.Parameters.AddWithValue("@EmployeeID", internalOrder.EmployeeID);
                        cmd1.Parameters.AddWithValue("@DepartmentID", internalOrder.DepartmentID);
                        cmd1.Parameters.AddWithValue("@Description", internalOrder.Description);
                        cmd1.Parameters.AddWithValue("@OrderComplete", internalOrder.OrderComplete);
                        cmd1.Parameters.AddWithValue("@DateOrdered", internalOrder.DateOrdered);
                        var temp            = cmd1.ExecuteScalar();
                        int internalOrderID = Convert.ToInt32(temp);


                        foreach (var line in lines)
                        {
                            var cmd2 = new SqlCommand(cmdText2, conn);
                            cmd2.CommandType = CommandType.StoredProcedure;
                            cmd2.Parameters.AddWithValue("@ItemID", line.ItemID);
                            cmd2.Parameters.AddWithValue("@InternalOrderID", internalOrderID);
                            cmd2.Parameters.AddWithValue("@OrderQty", line.OrderQty);
                            cmd2.Parameters.AddWithValue("@QtyReceived", line.QtyReceived);
                            rowsAffected += cmd2.ExecuteNonQuery();
                        }
                    }
                    scope.Complete();
                }
            }
            catch (Exception)
            {
                throw;
            }

            return(rowsAffected);
        }
 /// <summary>
 /// Load the list of pending work orders.
 /// </summary>
 private void LoadOrders()
 {
     try
     {
         InternalOrder.ReadInternalOrder();
         this.dgvInternalOrder.DataSource = null;
         this.dgvInternalOrder.DataSource = CoreSystem.InternalOrders;
         this.lblErrorList.Visible        = false;
     }
     catch (Exception ex)
     {
         this.btnAceptOrder.Enabled = false;
         this.lblErrorList.Visible  = true;
         this.lblErrorList.Text     = "There are no work orders to carry out.";
         InternalOrder.SaveErrorLogOrder(ex.Message);
     }
 }
        public static async void RemoveOrderTimeFromInternalOrder()
        {
            // create internal order
            InternalOrder internalOrder;

            using (var dbContext = new EfTestDbContext()) {
                var repo = new InternalOrderRepository(dbContext);
                var seq  = await repo.NextOrderNumber();

                internalOrder = new InternalOrder("W-{seq}");

                internalOrder.SetTime(new OrderTime("Test"));
                await repo.Update(internalOrder);

                await repo.SaveAsync();

                Debug.Assert(internalOrder.ID != Guid.Empty);
                Debug.Assert(null != internalOrder.OrderTimeID);
            }

            // remove order time
            Guid previousOrderTimeId;

            using (var dbContext = new EfTestDbContext()) {
                var repo  = new InternalOrderRepository(dbContext);
                var order = repo.Get(internalOrder.ID);
                previousOrderTimeId = order.OrderTime.ID;

                order.RemoveTime();

                Console.WriteLine($"Previous order time id {previousOrderTimeId}");

                await repo.Update(order);

                await repo.SaveAsync();
            }

            // check if OrderTime was deleted
            using (var dbContext = new EfTestDbContext()) {
                var order = dbContext.InternalOrders
                            .Include(x => x.OrderTime)
                            .Single(x => x.ID == internalOrder.ID);

                Debug.Assert(false == dbContext.OrderTimes.Any(x => x.ID == previousOrderTimeId), "OrderTime is still present");
            }
        }
        private async Task <bool> ExecuteAsync(InternalOrder internalOrder)
        {
            ExternalTrade externalTrade = null;

            string error = null;

            try
            {
                externalTrade = await _externalExchangeService.ExecuteLimitOrderAsync(internalOrder.AssetPairId,
                                                                                      internalOrder.Volume, internalOrder.Price, internalOrder.Type);
            }
            catch (NotEnoughLiquidityException)
            {
                error = Errors.NotEnoughLiquidity;
            }
            catch (Exception)
            {
                error = "An unexpected error occurred while executing order";
            }

            if (!string.IsNullOrEmpty(error))
            {
                internalOrder.Status       = InternalOrderStatus.Failed;
                internalOrder.RejectReason = error;

                await _internalOrderRepository.UpdateAsync(internalOrder);

                return(false);
            }

            // ReSharper disable once PossibleNullReferenceException
            internalOrder.ExecutedPrice  = externalTrade.Price;
            internalOrder.ExecutedVolume = externalTrade.Volume;
            internalOrder.TradeId        = externalTrade.Id;
            internalOrder.Status         = InternalOrderStatus.Executed;

            await _internalOrderRepository.UpdateAsync(internalOrder);

            await _positionService.CloseAsync(internalOrder, externalTrade);

            return(true);
        }
Exemple #17
0
 public void AddItemOrderTestInValidDepartmentLength()
 {
     internalOrder = new InternalOrder()
     {
         InternalOrderID = 8000,
         EmployeeID      = 100000,
         DepartmentID    = createString(51),
         Description     = "Food Order... maybe",
         OrderComplete   = false,
         DateOrdered     = DateTime.Now
     };
     _internalOrderLine = new VMInternalOrderLine()
     {
         ItemID      = 100000,
         OrderQty    = 100,
         QtyReceived = 100
     };
     lines = new List <VMInternalOrderLine>();
     lines.Add(_internalOrderLine);
     _internalOrderManager.CreateInternalOrder(internalOrder, lines);
 }
Exemple #18
0
        public async Task <CancelLimitOrderResponse> CancelLimitOrderAsync([FromBody] CancelLimitOrderRequest request)
        {
            InternalOrder internalOrder = await _internalOrderService.GetByIdAsync(request.OrderId);

            if (internalOrder == null)
            {
                throw new ValidationApiException(HttpStatusCode.NotFound, "Order not found");
            }

            if (internalOrder.Status != InternalOrderStatus.Cancelled &&
                internalOrder.Status != InternalOrderStatus.Rejected &&
                internalOrder.Status != InternalOrderStatus.Completed)
            {
                throw new ValidationApiException(HttpStatusCode.BadRequest, "Can not cancel order");
            }

            return(new CancelLimitOrderResponse
            {
                OrderId = request.OrderId
            });
        }
Exemple #19
0
 public void AddItemOrderTestInValidDescriptionBlank()
 {
     internalOrder = new InternalOrder()
     {
         InternalOrderID = 8000,
         EmployeeID      = 100000,
         DepartmentID    = "Events",
         Description     = "",
         OrderComplete   = false,
         DateOrdered     = DateTime.Now
     };
     _internalOrderLine = new VMInternalOrderLine()
     {
         ItemID      = 100000,
         OrderQty    = 100,
         QtyReceived = 100
     };
     lines = new List <VMInternalOrderLine>();
     lines.Add(_internalOrderLine);
     _internalOrderManager.CreateInternalOrder(internalOrder, lines);
 }
        private async Task ReleaseReservedFundsAsync(InternalOrder internalOrder)
        {
            Instrument instrument = await _instrumentService.TryGetByAssetPairIdAsync(internalOrder.AssetPairId);

            AssetPair assetPair = await _assetsServiceWithCache.TryGetAssetPairAsync(instrument.AssetPairId);

            string  assetId;
            decimal amount;

            if (internalOrder.Type == LimitOrderType.Sell)
            {
                assetId = assetPair.BaseAssetId;
                amount  = internalOrder.Volume;
            }
            else
            {
                Asset asset = await _assetsServiceWithCache.TryGetAssetAsync(assetPair.QuotingAssetId);

                assetId = assetPair.QuotingAssetId;
                amount  = (internalOrder.Volume * internalOrder.Price).TruncateDecimalPlaces(asset.Accuracy, true);
            }

            _log.InfoWithDetails("Releasing reserved funds for internal trade",
                                 new { OrderId = internalOrder.Id, Asset = assetId, Amount = amount });

            string walletId = await _settingsService.GetWalletIdAsync();

            try
            {
                await _lykkeExchangeService.TransferAsync(walletId, internalOrder.WalletId, assetId, amount);
            }
            catch (Exception exception)
            {
                _log.ErrorWithDetails(exception, "Can not transfer back reserved funds", internalOrder);
            }

            internalOrder.Status = InternalOrderStatus.Cancelled;
            await _internalOrderRepository.UpdateAsync(internalOrder);
        }
        public async Task CloseAsync(InternalOrder internalOrder, ExternalTrade externalTrade)
        {
            await _tradeService.RegisterAsync(externalTrade);

            Position position = Position.Create(internalOrder, externalTrade);

            await _positionRepository.InsertAsync(position);

            try
            {
                await _positionRepositoryPostgres.InsertAsync(position);
            }
            catch (Exception exception)
            {
                _log.ErrorWithDetails(exception, "An error occurred while updating position in the postgres DB",
                                      position);
            }

            await _summaryReportService.RegisterClosePositionAsync(position);

            _log.InfoWithDetails("Position closed", position);
        }
        public int InsertItemOrder(InternalOrder internalOrder, List <VMInternalOrderLine> lines)
        {
            int count = 0;

            _orders.Add(new VMInternalOrder()
            {
                InternalOrderID = internalOrder.InternalOrderID,
                EmployeeID      = internalOrder.EmployeeID,
                DepartmentID    = internalOrder.DepartmentID,
                Description     = internalOrder.Description,
                OrderComplete   = internalOrder.OrderComplete,
                DateOrdered     = internalOrder.DateOrdered
            });
            foreach (var line in lines)
            {
                count++;
                line.InternalOrderId = internalOrder.InternalOrderID;
                _lines.Add(line);
            }


            return(count);
        }
Exemple #23
0
        public static void Run()
        {
            var orderHandler = new OrderHandler();

            var onlineOrder = new OnlineOrder
            {
                ItemId       = "XP-23",
                Amount       = 42,
                EmailAddress = "*****@*****.**",
                PricePerItem = 12.4m
            };

            orderHandler.HandleOnlineOrder(onlineOrder);

            var internalOrder = new InternalOrder
            {
                ItemId       = "IW-41",
                Amount       = 2,
                DepartmentId = "LAB-01"
            };

            orderHandler.HandleInternalOrder(internalOrder);
        }
        private async Task <bool> ValidateBalanceAsync(InternalOrder internalOrder)
        {
            Instrument instrument = await _instrumentService.TryGetByAssetPairIdAsync(internalOrder.AssetPairId);

            AssetPair assetPair = await _assetsServiceWithCache.TryGetAssetPairAsync(instrument.AssetPairId);

            Asset   asset;
            decimal amount;

            if (internalOrder.Type == LimitOrderType.Sell)
            {
                asset = await _assetsServiceWithCache.TryGetAssetAsync(assetPair.QuotingAssetId);

                amount = (internalOrder.Volume * internalOrder.Price).TruncateDecimalPlaces(asset.Accuracy, true);
            }
            else
            {
                asset = await _assetsServiceWithCache.TryGetAssetAsync(assetPair.BaseAssetId);

                amount = internalOrder.Volume;
            }

            Balance balance = await _balanceService.GetByAssetIdAsync(ExchangeNames.Lykke, asset.Id);

            if (balance.Amount < amount)
            {
                internalOrder.Status       = InternalOrderStatus.Rejected;
                internalOrder.RejectReason = Errors.NotEnoughLiquidity;

                await _internalOrderRepository.UpdateAsync(internalOrder);

                return(false);
            }

            return(true);
        }
        public async Task <InternalOrderModel> GetByIdAsync(string internalOrderId)
        {
            InternalOrder internalOrder = await _internalOrderService.GetByIdAsync(internalOrderId);

            return(Mapper.Map <InternalOrderModel>(internalOrder));
        }
        private async Task CompleteAsync(InternalOrder internalOrder)
        {
            internalOrder.Status = InternalOrderStatus.Completed;

            await _internalOrderRepository.UpdateAsync(internalOrder);
        }
    /// <summary>
    /// Creates or updates an existing internal order
    /// </summary>
    /// <param name="order">The updated order to be saved</param>
    /// <param name="orderConflictHandler">Handler for getting order conflict notifications. First parameter is original order, second parameter is the new order</param>
    public async Task Update(InternalOrder order, Action <InternalOrder, InternalOrder> orderConflictHandler = null)
    {
        // detach if already attached
        var entry = _context.Entry(order);

        if (entry.State != EntityState.Detached)
        {
            entry.State = EntityState.Detached;
        }

        // check if another entity is attached
        var existingTrackedEntities = _context.ChangeTracker.Entries <InternalOrder>().Where(x => x.Entity.ID == order.ID).ToList();

        foreach (var e in existingTrackedEntities)
        {
            e.State = EntityState.Detached;
        }


        // find original order
        var originalOrder = await _context.InternalOrders
                            .AsNoTracking()
                            .Include(io => io.OrderTime)
                            .SingleOrDefaultAsync(x => x.ID == order.ID);

        if (originalOrder == null)
        {
            // only order is in the added state
            _context.Attach(order);
            _context.Entry(order).State = EntityState.Added;

            if (order.OrderTime != null)
            {
                _context.Entry(order.OrderTime).State = EntityState.Added;
            }
            return;
        }


        _context.Attach(order);
        _context.Entry(order).State = EntityState.Modified;
        if (originalOrder.OrderTime != null)
        {
            // remove & add or update
            if (order.OrderTime == null)
            {
                var trackedOrderTime = _context.ChangeTracker.Entries <OrderTime>().Where(x => x.Entity.ID == originalOrder.OrderTimeID).SingleOrDefault();
                if (trackedOrderTime != null)
                {
                    trackedOrderTime.State = EntityState.Deleted;
                }
                else
                {
                    _context.Remove(originalOrder.OrderTime);
                }
            }
            else
            {
                // new or updated OrderTime
                if (order.OrderTime.ID == originalOrder.OrderTime.ID)
                {
                    // modify
                    _context.Entry(order.OrderTime).State = EntityState.Modified;
                }
                else
                {
                    var trackedOrderTime = _context.ChangeTracker.Entries <OrderTime>().Where(x => x.Entity.ID == originalOrder.OrderTimeID).SingleOrDefault();
                    if (trackedOrderTime != null)
                    {
                        trackedOrderTime.State = EntityState.Deleted;
                    }
                    else
                    {
                        _context.Remove(originalOrder.OrderTime);
                    }
                    _context.Entry(order.OrderTime).State = EntityState.Added;
                }
            }
        }
    }