public async Task <Attempt <CsvImportSummaryModel> > SaveImportAsync(string operationId, CancellationToken cancellationToken = default(CancellationToken))
        {
            var validRecords = _csvCache.Find(operationId);

            if (validRecords == null)
            {
                return(Attempt <CsvImportSummaryModel> .Fail(new NotFoundException($"No import data has found. Please upload again.")));
            }

            var toCreate = validRecords.Where(r => r.Operation == Operation.Create);
            var toDelete = validRecords.Where(r => r.Operation == Operation.Delete);
            var toUpdate = validRecords.Where(r => r.Operation == Operation.Update);

            foreach (var record in toDelete)
            {
                await _productRepository.DeleteAsync(record.ProductId, cancellationToken);
            }

            var productFamilies = (await _productFamilyRepository.GetAllAsync(cancellationToken)).ToList();

            foreach (var record in toCreate)
            {
                var existingProductFamily = productFamilies.SingleOrDefault(pf => pf.Code == record.CsvItem.FamilyCode);
                var product = record.ToProduct(existingProductFamily);
                if (existingProductFamily == null)
                {
                    productFamilies.Add(product.ProductFamily);
                }
                _productRepository.Create(product);
            }

            var existingProducts = await _productRepository.GetAllBySkusAsync(toUpdate.Select(co => co.CsvItem.Sku), cancellationToken);

            foreach (var record in toUpdate)
            {
                var existingProduct = existingProducts.Single(pf => pf.Sku == record.CsvItem.Sku);
                _productRepository.Update(record.ToProduct(existingProduct));
            }

            var saveAttempt = await _productRepository.SaveAsync(cancellationToken);

            if (!saveAttempt.Success)
            {
                return(Attempt <CsvImportSummaryModel> .Fail(saveAttempt.Exception));
            }

            var result = new CsvImportSummaryModel {
                OperationId       = operationId,
                CreateRecordCount = toCreate.Count(),
                DeleteRecordCount = toDelete.Count(),
                UpdateRecordCount = toUpdate.Count()
            };

            return(Attempt <CsvImportSummaryModel> .Succeed(result));
        }
        public Attempt <CsvImportSummaryModel> GetSummary(string operationId)
        {
            var validRecords   = _csvCache.Find(operationId);
            var invalidRecords = _csvErrorCache.Find(operationId);

            if (validRecords == null && invalidRecords == null)
            {
                return(Attempt <CsvImportSummaryModel> .Fail(new NotFoundException($"No import data has found. Please upload again.")));
            }

            var summary = new CsvImportSummaryModel
            {
                OperationId        = operationId,
                InvalidRecordCount = invalidRecords?.Count ?? 0,
                CreateRecordCount  = validRecords?.Count(r => r.Operation == Operation.Create) ?? 0,
                DeleteRecordCount  = validRecords?.Count(r => r.Operation == Operation.Delete) ?? 0,
                UpdateRecordCount  = validRecords?.Count(r => r.Operation == Operation.Update) ?? 0,
            };

            return(Attempt <CsvImportSummaryModel> .Succeed(summary));
        }