private async Task ValidateAgainstExistingAsync(string operationId, IList <CsvOperationModel> csvOperations, CancellationToken cancellationToken = default(CancellationToken))
        {
            // TODO: Use cache/store and request it one by one if there will be to many product family
            var productFamilies = await _productFamilyRepository.GetAllAsync(cancellationToken);

            var operationsToRemove = new List <CsvOperationModel>();

            foreach (var csvOperation in csvOperations)
            {
                var productFamily = productFamilies.SingleOrDefault(pf => pf.Code == csvOperation.CsvItem.FamilyCode);
                if (productFamily != null && productFamily.Category != csvOperation.CsvItem.Category)
                {
                    var csvError = new CsvErrorModel(
                        csvOperation.Line,
                        $"Inconsistent category with against products. Category should be {productFamily.Category}.");
                    _csvErrorCache.Add(operationId, csvError);
                    operationsToRemove.Add(csvOperation);
                }
            }

            foreach (var csvOperation in operationsToRemove)
            {
                csvOperations.Remove(csvOperation);
            }
        }
        public async Task <Attempt <string> > ImportCsvAsync(Stream fileStream, bool replaceAll, CancellationToken cancellationToken = default(CancellationToken))
        {
            cancellationToken.ThrowIfCancellationRequested();

            var operationId   = Guid.NewGuid().ToString();
            var csvOperations = new List <CsvOperationModel>();

            fileStream.Position = 0;
            using (var textReader = new StreamReader(fileStream))
            {
                var csvReader = new CsvReader(textReader, _csvConfiguration);

                var headerValidated = false;
                while (csvReader.Read())
                {
                    Exception headerException;
                    if (!headerValidated)
                    {
                        if (!TryValidateCsvHeader(csvReader, out headerException))
                        {
                            return(Attempt <string> .Fail(new Exception(headerException.Message)));
                        }

                        headerValidated = true;
                        continue;
                    }

                    try
                    {
                        csvOperations.Add(new CsvOperationModel(csvReader.GetRecord <CsvModel>(), csvReader.Context.Row));
                    }
                    catch (Exception ex)
                    {
                        var csvError = new CsvErrorModel(csvReader.Context.CurrentIndex, new List <string>()
                        {
                            ex.Message
                        });
                        _csvErrorCache.Add(operationId, csvError);
                    }
                }
            }

            ValidateOperations(operationId, csvOperations);

            if (!replaceAll)
            {
                await ValidateAgainstExistingAsync(operationId, csvOperations);
            }

            await SetOperationTypesAsync(replaceAll, csvOperations, cancellationToken);

            foreach (var csvOperation in csvOperations)
            {
                _csvCache.Add(operationId, csvOperation);
            }

            return(Attempt <string> .Succeed(operationId));
        }
        public void Add(string key, CsvErrorModel csvError)
        {
            var cachedItems = Find(key);

            if (cachedItems == null)
            {
                cachedItems = new List <CsvErrorModel>();
            }

            cachedItems.Add(csvError);
            _cacheProvider.Add(key, cachedItems, TimeSpan.FromMinutes(20));
        }
        private void ValidateOperations(string operationId, IList <CsvOperationModel> csvOperations)
        {
            IDictionary <CsvOperationModel, ICollection <ValidationResult> > validationResults;

            if (!csvOperations.TryValidate(out validationResults))
            {
                foreach (var validationResult in validationResults.Where(v => v.Value.Any()))
                {
                    var csvError = new CsvErrorModel(validationResult.Key.Line, validationResult.Value.Select(vr => vr.ErrorMessage).ToList());

                    _csvErrorCache.Add(operationId, csvError);
                    csvOperations.Remove(validationResult.Key);
                }
            }
        }