public void ItWillInvalidateTransactionFilterModel()
        {
            var filterModel = new TransactionFilterDomainModel
            {
                Page             = -1,
                PageSize         = -25,
                StartDate        = new DateTime(year: 2021, month: 1, day: 1),
                EndDate          = new DateTime(year: 2020, month: 1, day: 1),
                Symbol           = "ABCDEFGHIJKLMNOPQRSTUVWXYZ",
                TransactionType  = '0',
                OrderByField     = "FakeField",
                OrderByDirection = '0'
            };

            using (var mock = AutoMock.GetLoose())
            {
                var service = mock.Create <TransactionService>();

                var result = service.ValidateTransactionFilterModel(filterModel);

                Assert.NotNull(result);
                Assert.Equal(7, result.Count());
                Assert.False(result.IsValid);
            }
        }
        public void ItWillValidateTransactionFilterModel()
        {
            var filterModel = new TransactionFilterDomainModel
            {
                Page             = 1,
                PageSize         = 25,
                StartDate        = new DateTime(year: 2020, month: 1, day: 1),
                EndDate          = new DateTime(year: 2021, month: 1, day: 1),
                Symbol           = "ABC",
                TransactionType  = 'B',
                OrderByField     = "TradeDate",
                OrderByDirection = 'A'
            };

            using (var mock = AutoMock.GetLoose())
            {
                var service = mock.Create <TransactionService>();

                var result = service.ValidateTransactionFilterModel(filterModel);

                Assert.NotNull(result);
                Assert.Empty(result);
                Assert.True(result.IsValid);
            }
        }
        public async Task <PaginatedResult <TransactionDomainModel> > GetFilteredAsync(TransactionFilterDomainModel filterModel, string accessKey)
        {
            var filterEntityModel = _mapper.Map <TransactionFilterEntityModel>(filterModel);

            filterEntityModel.AccessKey = accessKey;

            var parameters = CreateParametersForGetFilteredAsync(filterEntityModel);

            using var connection = _connectionFactory.NewConnection();
            await connection.OpenAsync();

            var reader = await connection.QueryMultipleAsync(
                "StoGetFilteredTransactions",
                parameters,
                commandType : CommandType.StoredProcedure);

            var transactions     = reader.Read <TransactionEntityModel>().ToList();
            var totalRecordCount = reader.Read <int>().SingleOrDefault();

            return(new PaginatedResult <TransactionDomainModel>(
                       results: _mapper.Map <IEnumerable <TransactionDomainModel> >(transactions),
                       metadata: CreatePaginationMetadata(filterEntityModel, totalRecordCount)));
        }
        public ModelStateDictionary ValidateTransactionFilterModel(TransactionFilterDomainModel filterModel)
        {
            var errors = new ModelStateDictionary();

            if (filterModel.Page < 1)
            {
                errors.AddModelError("Page", "The page number cannot be less than one.");
            }

            if (filterModel.PageSize < 1)
            {
                errors.AddModelError("PageSize", "The page size cannot be less than 1.");
            }

            if (filterModel.StartDate.HasValue && filterModel.EndDate.HasValue)
            {
                if (filterModel.StartDate.Value >= filterModel.EndDate.Value)
                {
                    errors.AddModelError("StartDate", "The start date must occur before the end date.");
                }
            }

            if (!string.IsNullOrEmpty(filterModel.Symbol) && filterModel.Symbol.Length > 10)
            {
                errors.AddModelError("Symbol", "The provided symbol must not exceed 10 characters.");
            }

            if (filterModel.TransactionType.HasValue)
            {
                char inputTransactionType = filterModel.TransactionType.Value;

                var validTransactionTypes = new char[] { 'B', 'S' };

                if (!validTransactionTypes.Contains(inputTransactionType))
                {
                    errors.AddModelError("TransactionType", "The transaction type must be a valid type: B - Buy, S - Sell.");
                }
            }

            if (!string.IsNullOrEmpty(filterModel.OrderByField))
            {
                string inputOrderByField = filterModel.OrderByField;

                var validOrderByFields = new string[]
                {
                    "TransactionId",
                    "Symbol",
                    "TradeDate",
                    "TradePrice",
                    "Quantity",
                    "Notional"
                };

                if (!validOrderByFields.Select(x => x.ToLower())
                    .Contains(inputOrderByField.ToLower()))
                {
                    errors.AddModelError("OrderByField", $"The order by field must be a valid field: {string.Join(", ", validOrderByFields)}.");
                }
            }

            if (filterModel.OrderByDirection.HasValue)
            {
                char inputOrderByDirection = filterModel.OrderByDirection.Value;

                var validOrderByDirections = new char[] { 'A', 'D' };

                if (!validOrderByDirections.Contains(inputOrderByDirection))
                {
                    errors.AddModelError("OrderByDirection", "The order by direction must be a valid direction: A - Ascending, D - Descending.");
                }
            }

            return(errors);
        }
 public async Task <PaginatedResult <TransactionDomainModel> > GetFilteredTransactions(TransactionFilterDomainModel filterModel, string accessKey)
 {
     return(await _transactionsRepository.GetFilteredAsync(filterModel, accessKey));
 }