public List <BidInfoViewModel> GetAllBidsForAuction(Guid auctionId)
        {
            var auction = _applicationDbContext.Auctions.Include("Organizations").Include("Bids").SingleOrDefault(p => p.Id == auctionId);

            if (auction == null)
            {
                throw new Exception($"Аукциона с таким id {auctionId} не существует");
            }

            var activeBidStatus = _applicationDbContext.BidStatuses.SingleOrDefault(p => p.StatusName == "Active").Id;

            if (activeBidStatus == null)
            {
                BidStatus status = new BidStatus()
                {
                    Id         = Guid.NewGuid(),
                    StatusName = "Active"
                };
                activeBidStatus = status.Id;
            }

            var bidForAuction = auction.Bids.Where(p => p.BidStatusId == activeBidStatus).ToList();

            if (bidForAuction.Count == 0)
            {
                throw new Exception($"По аукциону {auctionId} нет активных ставок");
            }

            List <BidInfoViewModel> bids = new List <BidInfoViewModel>();

            foreach (Bid item in bidForAuction)
            {
                BidInfoViewModel bid = new BidInfoViewModel()
                {
                    BidId              = item.Id.ToString(),
                    AuctionId          = auctionId.ToString(),
                    AuctionType        = item.Auction.AuctionType.ToString(),
                    AuctionDescription = item.Auction.Description,
                    BidStatus          = item.BidStatus.StatusName,
                    OrganizationId     = item.Organization.Id.ToString(),
                    OrganizationName   = item.Organization.FullName,
                    Price              = item.Price,
                    CreatedDate        = item.CreatedDate,
                    BidDescription     = item.Description
                };
                bids.Add(bid);
            }
            return(bids);
        }
        public void WinnerInAuction(BidInfoViewModel model)
        {
            var auction = _applicationDbContext.Auctions.SingleOrDefault(p => p.Id.ToString() == model.AuctionId);

            if (auction == null)
            {
                throw new Exception($"Аукциона с id {model.AuctionId} не существует");
            }

            var organization = _applicationDbContext.Organizations.Include("Transactions").Include("OrganizationRatings")
                               .SingleOrDefault(p => p.Id.ToString() == model.OrganizationId);

            if (organization == null)
            {
                throw new Exception($"Организации с id {model.OrganizationId} не существует");
            }

            var IsAuctionCreator = _applicationDbContext.Auctions
                                   .Any(p => p.Id.ToString() == model.AuctionId && p.OrganizationId.ToString() == model.OrganizationId);

            if (IsAuctionCreator)
            {
                throw new Exception($"Организация-создатель аукциона {model.AuctionId} не может быть победителем данного аукциона");
            }


            var bid = _applicationDbContext.Bids.SingleOrDefault(p => p.Id.ToString() == model.BidId);

            if (bid == null)
            {
                throw new Exception("Такой ставки не существует");
            }

            bid.IsWin = true;
            _applicationDbContext.SaveChanges();

            Transaction transaction = new Transaction()
            {
                Id = Guid.NewGuid(),
                TransactionType = TransactionType.Withdraw,
                Sum             = model.Price,
                TransactionDate = DateTime.Now,
                OrganizationId  = new Guid(model.OrganizationId),
                Description     = $"Withdraw bid price for auction {model.AuctionId}"
            };

            _applicationDbContext.Transactions.Add(transaction);
            _applicationDbContext.SaveChanges();
        }
        public void AuctionManagementService_ElectWinnerInAuction()
        {
            ApplicationDbContext applicationDb = new ApplicationDbContext();

            applicationDb.Database.CreateIfNotExists();

            OrganizationType organizationType = new OrganizationType()
            {
                Id   = Guid.NewGuid(),
                Name = "TstTypeA_04"
            };

            applicationDb.OrganizationTypes.Add(organizationType);
            applicationDb.SaveChanges();

            Organization auctionMaster = new Organization()
            {
                Id                 = Guid.NewGuid(),
                FullName           = "TestCompanyA_04",
                RegistrationDate   = DateTime.Now,
                OrganizationTypeId = organizationType.Id
            };

            applicationDb.Organizations.Add(auctionMaster);
            applicationDb.SaveChanges();

            Organization auctionParticipant = new Organization()
            {
                Id                 = Guid.NewGuid(),
                FullName           = "TestCompanyA_042",
                RegistrationDate   = DateTime.Now,
                OrganizationTypeId = organizationType.Id
            };

            applicationDb.Organizations.Add(auctionParticipant);
            applicationDb.SaveChanges();

            AuctionType auctionType = new AuctionType()
            {
                Id   = Guid.NewGuid(),
                Name = "TestAuctionType_04"
            };

            applicationDb.AuctionTypes.Add(auctionType);
            applicationDb.SaveChanges();

            Auction auction = new Auction()
            {
                Id                      = Guid.NewGuid(),
                Description             = "test_any description_04",
                MinRatingForParticipant = 9.5,
                StartPrice              = 600000M,
                MinPrice                = 100000M,
                PriceStep               = 50000M,
                StartDate               = new DateTime(2019, 4, 26),
                FinishDate              = new DateTime(2019, 5, 22),
                Status                  = AuctionStatus.Active,
                AuctionTypeId           = auctionType.Id,
                OrganizationId          = auctionMaster.Id
            };

            applicationDb.Auctions.Add(auction);
            applicationDb.SaveChanges();

            Transaction depositTrans = new Transaction()
            {
                Id = Guid.NewGuid(),
                TransactionType = TransactionType.Deposit,
                Sum             = 400000,
                TransactionDate = DateTime.Now,
                OrganizationId  = auctionParticipant.Id
            };

            applicationDb.Transactions.Add(depositTrans);
            applicationDb.SaveChanges();

            OrganizationRating rating = new OrganizationRating()
            {
                Id             = Guid.NewGuid(),
                Score          = 10,
                OrganizationId = auctionParticipant.Id
            };

            applicationDb.OrganizationRatings.Add(rating);
            applicationDb.SaveChanges();

            var activeBidStatus = applicationDb.BidStatuses.SingleOrDefault(p => p.StatusName == "Active");

            if (activeBidStatus == null)
            {
                BidStatus status = new BidStatus()
                {
                    Id         = Guid.NewGuid(),
                    StatusName = "Active"
                };
                applicationDb.BidStatuses.Add(status);
                applicationDb.SaveChanges();
                activeBidStatus = status;
            }

            Bid bid = new Bid()
            {
                Id             = Guid.NewGuid(),
                Price          = 200000M,
                CreatedDate    = DateTime.Now,
                BidStatusId    = activeBidStatus.Id,
                AuctionId      = auction.Id,
                OrganizationId = auctionParticipant.Id
            };

            applicationDb.Bids.Add(bid);
            applicationDb.SaveChanges();

            BidInfoViewModel model = new BidInfoViewModel()
            {
                BidId          = bid.Id.ToString(),
                AuctionId      = auction.Id.ToString(),
                OrganizationId = auctionParticipant.Id.ToString(),
                CreatedDate    = DateTime.Now,
                Price          = bid.Price
            };

            AuctionManagementService sut = new AuctionManagementService();

            sut.ElectWinnerInAuction(model);

            Bid         newBid      = applicationDb.Bids.SingleOrDefault(p => p.Id.ToString() == model.BidId);
            Transaction transaction = applicationDb.Transactions
                                      .SingleOrDefault(p => p.Sum == model.Price && p.TransactionType == TransactionType.Withdraw &&
                                                       p.OrganizationId.ToString() == model.OrganizationId);

            Assert.IsNotNull(newBid);
            Assert.IsNotNull(transaction);
        }
        public List <BidInfoViewModel> GetBidsForAuctionWithFitOrganizationRatingAndBalance(Guid auctionId)
        {
            var auction = _applicationDbContext.Auctions.Include("Organizations").Include("Bids").SingleOrDefault(p => p.Id == auctionId);

            if (auction == null)
            {
                throw new Exception($"Аукциона с таким id {auctionId} не существует");
            }

            var activeBidStatus = _applicationDbContext.BidStatuses.SingleOrDefault(p => p.StatusName == "Active").Id;

            if (activeBidStatus == null)
            {
                BidStatus status = new BidStatus()
                {
                    Id         = Guid.NewGuid(),
                    StatusName = "Active"
                };
                activeBidStatus = status.Id;
            }

            var allBids = auction.Bids.Where(p => p.BidStatusId == activeBidStatus).ToList();

            if (allBids.Count == 0)
            {
                throw new Exception($"По аукциону {auctionId} нет активных ставок");
            }

            List <Bid> bidsWithFitRating = new List <Bid>();

            foreach (Bid item in allBids)
            {
                var org = item.OrganizationId;
                var avg = _applicationDbContext.OrganizationRatings.Where(p => p.OrganizationId == org).Average(p => p.Score);
                if (avg >= auction.MinRatingForParticipant)
                {
                    bidsWithFitRating.Add(item);
                }
            }
            if (bidsWithFitRating.Count == 0)
            {
                throw new Exception($"По аукциону {auctionId} нет ставок от организаций с нужным рейтингом");
            }

            List <Bid> bidsWithFitRatingBalance = new List <Bid>();

            foreach (Bid item in bidsWithFitRating)
            {
                var org         = item.OrganizationId;
                var sumDeposits = _applicationDbContext.Transactions
                                  .Where(p => p.OrganizationId == org && p.TransactionType == TransactionType.Deposit).Sum(p => p.Sum);
                var sumWithdraws = _applicationDbContext.Transactions
                                   .Where(p => p.OrganizationId == org && p.TransactionType == TransactionType.Withdraw).Sum(p => p.Sum);
                if (sumDeposits - sumWithdraws > item.Price)
                {
                    bidsWithFitRatingBalance.Add(item);
                }
            }
            if (bidsWithFitRatingBalance.Count == 0)
            {
                throw new Exception($"По аукциону {auctionId} нет ставок от организаций с достаточным балансом");
            }

            List <BidInfoViewModel> bids = new List <BidInfoViewModel>();

            foreach (Bid item in bidsWithFitRatingBalance)
            {
                BidInfoViewModel bid = new BidInfoViewModel()
                {
                    BidId              = item.Id.ToString(),
                    AuctionId          = auctionId.ToString(),
                    AuctionType        = item.Auction.AuctionType.ToString(),
                    AuctionDescription = item.Auction.Description,
                    BidStatus          = item.BidStatus.StatusName,
                    OrganizationId     = item.Organization.Id.ToString(),
                    OrganizationName   = item.Organization.FullName,
                    Price              = item.Price,
                    CreatedDate        = item.CreatedDate,
                    BidDescription     = item.Description
                };
                bids.Add(bid);
            }
            return(bids);
        }
        public void ElectWinnerInAuction(BidInfoViewModel model)
        {
            var auction = _applicationDbContext.Auctions.SingleOrDefault(p => p.Id.ToString() == model.AuctionId);

            if (auction == null)
            {
                throw new Exception($"Аукциона с id {model.AuctionId} не существует");
            }

            var organization = _applicationDbContext.Organizations.Include("Transactions").Include("OrganizationRatings")
                               .SingleOrDefault(p => p.Id.ToString() == model.OrganizationId);

            if (organization == null)
            {
                throw new Exception($"Организации с id {model.OrganizationId} не существует");
            }

            var IsAuctionCreator = _applicationDbContext.Auctions
                                   .Any(p => p.Id.ToString() == model.AuctionId && p.OrganizationId.ToString() == model.OrganizationId);

            if (IsAuctionCreator)
            {
                throw new Exception($"Организация-создатель аукциона {model.AuctionId} не может быть победителем данного аукциона");
            }

            //проверка суммы на балансе организации-победителя
            var organizationTransactions = organization.Transactions.ToList();

            if (organizationTransactions.Count == 0)
            {
                throw new Exception($"У организации {organization.FullName} нулевой баланс");
            }

            var organizationBalance = organizationTransactions
                                      .Where(p => p.TransactionType == TransactionType.Deposit).Sum(p => p.Sum) -
                                      organizationTransactions.Where(p => p.TransactionType == TransactionType.Withdraw).Sum(p => p.Sum);

            if (organizationBalance < model.Price)
            {
                throw new Exception($"У организации {organization.FullName} не хватает средств на балансе для оплаты своей ставки на аукционе");
            }

            //проверка рейтинга организации-победителя
            var organizationAvgScore = organization.OrganizationRatings.Average(p => p.Score);

            if (organizationAvgScore < auction.MinRatingForParticipant)
            {
                throw new Exception($"У организации {organization.FullName} нет нужного рейтинга для участия в аукционе");
            }

            var bid = _applicationDbContext.Bids.SingleOrDefault(p => p.Id.ToString() == model.BidId);

            if (bid == null)
            {
                throw new Exception("Такой ставки не существует");
            }

            bid.IsWin = true;
            _applicationDbContext.SaveChanges();

            Transaction transaction = new Transaction()
            {
                Id = Guid.NewGuid(),
                TransactionType = TransactionType.Withdraw,
                Sum             = model.Price,
                TransactionDate = DateTime.Now,
                OrganizationId  = new Guid(model.OrganizationId),
                Description     = $"Withdraw bid price for auction {model.AuctionId}"
            };

            _applicationDbContext.Transactions.Add(transaction);
            _applicationDbContext.SaveChanges();
        }