예제 #1
0
    public async Task <DalResult> BuyFromOfferAsync(int buyerid, long quantity, OfferEntity offer, bool oldestFirst)
    {
        if (buyerid <= 0)
        {
            return(new(DalErrorCode.Invalid, new("Buyer id is invalid")));
        }
        if (quantity == 0)
        {
            return(new(DalErrorCode.Invalid, new("Quantity must be greater than zero")));
        }
        if (offer is null)
        {
            return(new(DalErrorCode.Invalid, new ArgumentNullException(nameof(offer))));
        }
        if (offer.UserId <= 0)
        {
            return(new(DalErrorCode.Invalid, new Exception("Seller id in offer is invalid")));
        }
        var bean = await _beanRepository.ReadAsync(offer.BeanId);

        if (bean is null)
        {
            return(new(DalErrorCode.NotFound, new Exception($"No bean with the id {offer.BeanId} was found")));
        }
        var buyer = await _userRepository.ReadAsync(buyerid);

        if (buyer is null)
        {
            return(new(DalErrorCode.NotFound, new($"No user with the id {buyerid} was found")));
        }
        if (buyer.Balance < quantity * offer.Price)
        {
            return(new(DalErrorCode.NSF, new("Buyer does not have sufficient funds")));
        }
        var seller = await _userRepository.ReadAsync(offer.UserId);

        if (seller is null)
        {
            return(new(DalErrorCode.NotFound, new($"No user with the id {offer.User} was found")));
        }
        var beansHeld = await _holdingRepository.BeansHeldByUserAndBeanAsync(offer.UserId, offer.BeanId);

        if (quantity > beansHeld)
        {
            return(new(DalErrorCode.NSF, new("Seller has insufficient beans")));
        }
        var holdings = await _holdingRepository.GetHoldingsAsync(oldestFirst, offer.UserId, offer.BeanId, quantity);

        if (holdings.Length == 0)
        {
            return(new(DalErrorCode.NotFound, new("Unable to locate holdings to satisfy sale")));
        }
        using var conn = new SqlConnection(ConnectionString);
        await conn.OpenAsync();

        using var transaction = await conn.BeginTransactionAsync();

        try
        {
            var  profit    = 0M;
            long satisfied = 0;
            var  ix        = 0;
            while (ix < holdings.Length - 1)
            {
                var holding = await _holdingRepository.ReadAsync(holdings[ix]);

                if (holding is null)
                {
                    await transaction.RollbackAsync();

                    return(new(DalErrorCode.NotFound, new($"No holding with the id {holdings[ix]} was found")));
                }
                var sale = new SaleEntity
                {
                    Id           = 0,
                    UserId       = seller.Id,
                    BeanId       = bean.Id,
                    PurchaseDate = holding.PurchaseDate,
                    SaleDate     = DateTime.UtcNow,
                    CostBasis    = holding.Price,
                    Quantity     = holding.Quantity,
                    SalePrice    = offer.Price,
                    Bean         = null
                };
                var insresult = await conn.InsertAsync(sale, transaction : transaction);

                profit    += holding.Quantity * offer.Price;
                satisfied += holding.Quantity;
                await conn.DeleteAsync(holding, transaction : transaction);

                ix++;
            }
            var lastHolding = await _holdingRepository.ReadAsync(holdings[^ 1]);
예제 #2
0
 public async Task <long> BeansHeldByUserAndBeanAsync(int userid, int beanid) => await _holdingRepository.BeansHeldByUserAndBeanAsync(userid, beanid);