public static CourseDataUploadRowInfoCollection ToDataUploadRowCollection(this IEnumerable <CsvCourseRow> rows)
        {
            var rowInfos = new List <CourseDataUploadRowInfo>();

            foreach (var group in CsvCourseRow.GroupRows(rows))
            {
                var courseId = Guid.NewGuid();

                foreach (var row in group)
                {
                    rowInfos.Add(new CourseDataUploadRowInfo(row, rowNumber: rowInfos.Count + 2, courseId));
                }
            }

            return(new CourseDataUploadRowInfoCollection(rowInfos));
        }
Exemple #2
0
        public async Task ProcessCourseFile(Guid courseUploadId, Stream stream)
        {
            using (var dispatcher = _sqlQueryDispatcherFactory.CreateDispatcher(System.Data.IsolationLevel.ReadCommitted))
            {
                var setProcessingResult = await dispatcher.ExecuteQuery(new SetCourseUploadProcessing()
                {
                    CourseUploadId      = courseUploadId,
                    ProcessingStartedOn = _clock.UtcNow
                });

                if (setProcessingResult != SetCourseUploadProcessingResult.Success)
                {
                    await DeleteBlob();

                    return;
                }

                await dispatcher.Commit();
            }

            // At this point `stream` should be a CSV that's already known to conform to `CsvCourseRow`'s schema.
            // We read all the rows upfront because validation needs to group rows into courses.
            // We also don't expect massive files here so reading everything into memory is ok.
            List <CsvCourseRow> rows;

            using (var streamReader = new StreamReader(stream))
                using (var csvReader = CreateCsvReader(streamReader))
                {
                    rows = await csvReader.GetRecordsAsync <CsvCourseRow>().ToListAsync();
                }

            var rowsCollection = CreateCourseDataUploadRowInfoCollection();

            using (var dispatcher = _sqlQueryDispatcherFactory.CreateDispatcher(System.Data.IsolationLevel.ReadCommitted))
            {
                // If CourseName is empty, use the LearnAimRefTitle from LARS
                var learnAimRefs       = rowsCollection.Select(r => r.Data.LearnAimRef).Distinct();
                var learningDeliveries = await dispatcher.ExecuteQuery(new GetLearningDeliveries()
                {
                    LearnAimRefs = learnAimRefs
                });

                foreach (var row in rowsCollection)
                {
                    if (string.IsNullOrWhiteSpace(row.Data.CourseName))
                    {
                        row.Data.CourseName = learningDeliveries[row.Data.LearnAimRef].LearnAimRefTitle;
                    }
                }

                var venueUpload = await dispatcher.ExecuteQuery(new GetCourseUpload()
                {
                    CourseUploadId = courseUploadId
                });

                var providerId = venueUpload.ProviderId;

                await AcquireExclusiveCourseUploadLockForProvider(providerId, dispatcher);

                await ValidateCourseUploadRows(dispatcher, courseUploadId, providerId, rowsCollection);

                await dispatcher.Commit();
            }

            await DeleteBlob();

            Task DeleteBlob()
            {
                var blobName = $"{Constants.CoursesFolder}/{courseUploadId}.csv";

                return(_blobContainerClient.DeleteBlobIfExistsAsync(blobName));
            }

            CourseDataUploadRowInfoCollection CreateCourseDataUploadRowInfoCollection()
            {
                // N.B. It's important we maintain ordering here; RowNumber needs to match the input

                var grouped        = CsvCourseRow.GroupRows(rows);
                var groupCourseIds = grouped.Select(g => (CourseId: Guid.NewGuid(), Rows: g)).ToArray();

                var rowInfos = new List <CourseDataUploadRowInfo>(rows.Count);

                foreach (var row in rows)
                {
                    var courseId = groupCourseIds.Single(g => g.Rows.Contains(row)).CourseId;
                    row.LearnAimRef = NormalizeLearnAimRef(row.LearnAimRef);

                    rowInfos.Add(new CourseDataUploadRowInfo(row, rowNumber: rowInfos.Count + 2, courseId));
                }

                return(new CourseDataUploadRowInfoCollection(rowInfos));
            }
        }