/// <summary> /// reusable method /// </summary> /// <param name="fileAsZipInUTF8"></param> /// <param name="OverwriteMethod"></param> /// <param name="SubTypeID"> /// usually empty value. /// we use the parameter for sub types /// eg, sales order that derive from transaction /// eg, invoice that derive from transaction /// eg, visit that derive from activity /// in that case we take the SubTypeID from the metadata endpoint (see GetSubTypesMetadata method) /// The custom fields are TSA fields /// </param> /// <returns></returns> /// <remarks> /// 1. the post body is in UTF8 /// </remarks> private BulkUploadResponse BulkUploadOfZip(byte[] fileAsZipInUTF8, eOverwriteMethod OverwriteMethod, string SubTypeID = null) { string RequestUri = (SubTypeID == null || SubTypeID.Length == 0) ? string.Format("bulk/{0}/csv_zip", ResourceName) : string.Format("bulk/{0}/{1}/csv_zip", ResourceName, SubTypeID); //eg, for transaction or activity Dictionary <string, string> dicQueryStringParameters = new Dictionary <string, string>(); dicQueryStringParameters.Add("overwrite", OverwriteMethod.ToString()); byte[] postBody = fileAsZipInUTF8; string contentType = "application/zip"; string accept = "application/json"; PepperiHttpClient PepperiHttpClient = new PepperiHttpClient(this.Authentication, this.Logger); PepperiHttpClientResponse PepperiHttpClientResponse = PepperiHttpClient.PostByteArraycontent( ApiBaseUri, RequestUri, dicQueryStringParameters, postBody, contentType, accept ); PepperiHttpClient.HandleError(PepperiHttpClientResponse); BulkUploadResponse result = PepperiJsonSerializer.DeserializeOne <BulkUploadResponse>(PepperiHttpClientResponse.Body); return(result); }
private BulkUploadResponse BulkUpload_OfJson(IEnumerable <TModel> data, eOverwriteMethod OverwriteMethod, IEnumerable <string> fieldsToUpload) { FlatModel FlatModel = PepperiFlatSerializer.MapDataToFlatModel(data, fieldsToUpload, "''"); string RequestUri = string.Format("bulk/{0}/json", ResourceName); Dictionary <string, string> dicQueryStringParameters = new Dictionary <string, string>(); dicQueryStringParameters.Add("overwrite", OverwriteMethod.ToString()); string postBody = PepperiJsonSerializer.Serialize(FlatModel); //null values are not serialzied. string contentType = "application/json"; string accept = "application/json"; PepperiHttpClient PepperiHttpClient = new PepperiHttpClient(this.Authentication, this.Logger); PepperiHttpClientResponse PepperiHttpClientResponse = PepperiHttpClient.PostStringContent( ApiBaseUri, RequestUri, dicQueryStringParameters, postBody, contentType, accept ); PepperiHttpClient.HandleError(PepperiHttpClientResponse); BulkUploadResponse result = PepperiJsonSerializer.DeserializeOne <BulkUploadResponse>(PepperiHttpClientResponse.Body); return(result); }
private BulkUploadResponse BulkUploadOfZip(IEnumerable <TModel> data, eOverwriteMethod OverwriteMethod, IEnumerable <string> fieldsToUpload, string FilePathToStoreZipFile, string SubTypeID = null) { FlatModel FlatModel = PepperiFlatSerializer.MapDataToFlatModel(data, fieldsToUpload, "''"); string CsvFileAsString = PepperiFlatSerializer.FlatModelToCsv(FlatModel); byte[] CsvFileAsZipInUTF8 = PepperiFlatSerializer.UTF8StringToZip(CsvFileAsString, FilePathToStoreZipFile); BulkUploadResponse result = BulkUploadOfZip(CsvFileAsZipInUTF8, OverwriteMethod, SubTypeID); return(result); }
public BulkUploadResponse BulkUpload(string csvFilePath, eOverwriteMethod OverwriteMethod, Encoding fileEncoding, string SubTypeID = "", string FilePathToStoreZipFile = null) { byte[] fileAsBinary = File.ReadAllBytes(csvFilePath); bool isToAddBOM = true; // UTF8 byte order mark is: 0xEF,0xBB,0xBF if (fileAsBinary[0] == 0xEF && fileAsBinary[1] == 0xBB && fileAsBinary[2] == 0xBF) { isToAddBOM = false; } byte[] fileAsUtf8 = Encoding.Convert(fileEncoding, Encoding.UTF8, fileAsBinary); string fileAsUtf8String = System.Text.Encoding.UTF8.GetString(fileAsUtf8); byte[] fileAsZipInUTF8 = PepperiFlatSerializer.UTF8StringToZip(fileAsUtf8String, FilePathToStoreZipFile, isToAddBOM); BulkUploadResponse result = BulkUploadOfZip(fileAsZipInUTF8, OverwriteMethod, SubTypeID); return(result); }
/// <summary> /// Upsert of collection As json or csv zip /// </summary> /// <param name="data"></param> /// <param name="OverrideMethod"></param> /// <param name="BulkUploadMethod"></param> /// <param name="fieldsToUpload"></param> /// <param name="FilePathToStoreZipFile">Optional. We can store the generated zip file for debugging purpose.</param> /// <returns></returns> public BulkUploadResponse BulkUpload(IEnumerable <TModel> data, eOverwriteMethod OverrideMethod, eBulkUploadMethod BulkUploadMethod, IEnumerable <string> fieldsToUpload, bool SaveZipFileInLocalDirectory = false, string SubTypeID = "") { //validate input if (fieldsToUpload == null || fieldsToUpload.Count() == 0) { throw new PepperiException("No header fields are specified."); } BulkUploadResponse BulkUploadResponse = null; switch (BulkUploadMethod) { case eBulkUploadMethod.Json: { BulkUploadResponse = BulkUpload_OfJson(data, OverrideMethod, fieldsToUpload); break; } case eBulkUploadMethod.Zip: { string FilePathToStoreZipFile = null; if (SaveZipFileInLocalDirectory) { string AssemblyLocation = Assembly.GetExecutingAssembly().Location; string AssemblyPath = Path.GetDirectoryName(AssemblyLocation); string zipDirectory = AssemblyPath; string zipFileName = "BulkUpload_" + this.ResourceName + ".zip"; FilePathToStoreZipFile = Path.Combine(zipDirectory, zipFileName); } BulkUploadResponse = BulkUploadOfZip(data, OverrideMethod, fieldsToUpload, FilePathToStoreZipFile, SubTypeID); break; } default: { throw new PepperiException("Invalid argument: the upload method is not supported."); } } return(BulkUploadResponse); }
public async Task <BulkUploadResponse> CompareAndProcessRegistrations(IList <TqRegistrationProfile> registrations) { var result = new BulkUploadResponse(); var ulns = new HashSet <int>(); //var seedValue = 0; //var entitiesToLoad = 10000; //var ulns = new HashSet<int>(); //var registrations = new List<TqRegistrationProfile>(); //var dateTimeNow = DateTime.Now; //Random random = new Random(); //for (int i = 1; i <= entitiesToLoad; i++) //{ // if (i <= 10000) // ulns.Add(seedValue + i); // var reg = new TqRegistrationProfile // { // //Id = i, // UniqueLearnerNumber = seedValue + i, // Firstname = "Firstname " + (seedValue + "XY" + i), // Lastname = "Lastname " + (seedValue + i), // DateofBirth = DateTime.Parse("17/01/1983") // }; // reg.TqRegistrationPathways = new List<TqRegistrationPathway> // { // new TqRegistrationPathway // { // TqProviderId = 1, // StartDate = DateTime.Parse("01/06/2020"), // Status = 1, // TqProvider = new TqProvider { TqAwardingOrganisationId = 1, TlProviderId = 1, TqAwardingOrganisation = new TqAwardingOrganisation { TlAwardingOrganisatonId = 1, TlPathwayId = 1 } }, // //TqProvider = new TqProvider { TqAwardingOrganisationId = 1, TlProviderId = 2, TqAwardingOrganisation = new TqAwardingOrganisation { TlAwardingOrganisatonId = 3, TlPathwayId = 5 } }, // TqRegistrationSpecialisms = new List<TqRegistrationSpecialism> // { // new TqRegistrationSpecialism // { // TlSpecialismId = 17, // StartDate = DateTime.Parse("21/07/2020"), // Status = 1 // } // } // } // }; // registrations.Add(reg); //} //var watch = System.Diagnostics.Stopwatch.StartNew(); //watch.Start(); registrations.ToList().ForEach(r => ulns.Add(r.UniqueLearnerNumber)); var existingRegistrationsFromDb = await ctx.TqRegistrationProfile.Where(x => ulns.Contains(x.UniqueLearnerNumber)) .Include(x => x.TqRegistrationPathways) .ThenInclude(x => x.TqRegistrationSpecialisms) .Include(x => x.TqRegistrationPathways) .ThenInclude(x => x.TqProvider) .ThenInclude(x => x.TqAwardingOrganisation) //.ThenInclude(x => x.TlAwardingOrganisaton) .ToListAsync(); //watch.Stop(); //var sec1 = watch.ElapsedMilliseconds; //watch.Restart(); var modifiedRegistrations = new List <TqRegistrationProfile>(); var modifiedRegistrationsToIgnore = new List <TqRegistrationProfile>(); var modifiedPathwayRecords = new List <TqRegistrationPathway>(); var modifiedSpecialismRecords = new List <TqRegistrationSpecialism>(); var ulnComparer = new TqRegistrationUlnEqualityComparer(); var comparer = new TqRegistrationRecordEqualityComparer(); var newRegistrations = registrations.Except(existingRegistrationsFromDb, ulnComparer).ToList(); var matchedRegistrations = registrations.Intersect(existingRegistrationsFromDb, ulnComparer).ToList(); var sameOrDuplicateRegistrations = matchedRegistrations.Intersect(existingRegistrationsFromDb, comparer).ToList(); if (matchedRegistrations.Count != sameOrDuplicateRegistrations.Count) { modifiedRegistrations = matchedRegistrations.Except(sameOrDuplicateRegistrations, comparer).ToList(); var tqRegistrationProfileComparer = new TqRegistrationProfileEqualityComparer(); var tqRegistrationPathwayComparer = new TqRegistrationPathwayEqualityComparer(); var tqRegistrationSpecialismComparer = new TqRegistrationSpecialismEqualityComparer(); modifiedRegistrations.ForEach(modifiedRegistration => { var existingRegistration = existingRegistrationsFromDb.FirstOrDefault(existingRegistration => existingRegistration.UniqueLearnerNumber == modifiedRegistration.UniqueLearnerNumber); if (existingRegistration != null) { var hasBothPathwayAndSpecialismsRecordsChanged = false; var hasOnlySpecialismsRecordChanged = false; var hasTqRegistrationProfileRecordChanged = !tqRegistrationProfileComparer.Equals(modifiedRegistration, existingRegistration); modifiedRegistration.Id = existingRegistration.Id; modifiedRegistration.TqRegistrationPathways.ToList().ForEach(p => p.TqRegistrationProfileId = existingRegistration.Id); var pathwayRegistrationsInDb = existingRegistration.TqRegistrationPathways.Where(s => s.Status == 1).ToList(); var pathwaysToAdd = modifiedRegistration.TqRegistrationPathways.Where(s => !pathwayRegistrationsInDb.Any(r => r.TqProviderId == s.TqProviderId)).ToList(); var pathwaysToUpdate = pathwaysToAdd.Count > 0 ? pathwayRegistrationsInDb : pathwayRegistrationsInDb.Where(s => modifiedRegistration.TqRegistrationPathways.Any(r => r.TqProviderId == s.TqProviderId)).ToList(); if (pathwaysToUpdate.Count > 0) { var hasProviderChanged = !pathwaysToUpdate.Any(x => modifiedRegistration.TqRegistrationPathways.Any(r => r.TqProvider.TlProviderId == x.TqProvider.TlProviderId)); var hasPathwayChanged = !pathwaysToUpdate.Any(x => modifiedRegistration.TqRegistrationPathways.Any(r => r.TqProvider.TqAwardingOrganisation.TlPathwayId == x.TqProvider.TqAwardingOrganisation.TlPathwayId)); if (hasPathwayChanged) { //TODO: Need to check if there is an active registration for another AO, if so show error message and reject the file var hasAoChanged = !pathwaysToUpdate.Any(x => modifiedRegistration.TqRegistrationPathways.Any(r => r.TqProvider.TqAwardingOrganisation.TlAwardingOrganisatonId == x.TqProvider.TqAwardingOrganisation.TlAwardingOrganisatonId)); if (hasAoChanged) { result.BulkUploadErrors.Add(new BulkUploadError { FieldName = "Uln", FieldValue = modifiedRegistration.UniqueLearnerNumber.ToString(), ErrorMessage = "There is active registration with another Awarding Organisation" }); } } if (!result.HasAnyErrors) { // change existing TqRegistrationPathway record status and related TqRegistrationSpecialism records status to "Changed" if (pathwaysToAdd.Count > 0) { pathwaysToUpdate.ForEach(pathwayToUpdate => { pathwayToUpdate.Status = 2; // update status to changed pathwayToUpdate.EndDate = DateTime.UtcNow; pathwayToUpdate.ModifiedBy = "LoggedIn User"; pathwayToUpdate.ModifiedOn = DateTime.UtcNow; pathwayToUpdate.TqRegistrationSpecialisms.Where(s => s.Status == 1).ToList().ForEach(specialismToUpdate => { specialismToUpdate.Status = 2; // update status to changed specialismToUpdate.EndDate = DateTime.UtcNow; specialismToUpdate.ModifiedBy = "LoggedIn User"; specialismToUpdate.ModifiedOn = DateTime.UtcNow; }); }); hasBothPathwayAndSpecialismsRecordsChanged = true; } else { modifiedRegistration.TqRegistrationPathways.ToList().ForEach(importPathwayRecord => { var existingPathwayRecord = pathwaysToUpdate.FirstOrDefault(p => p.TqProviderId == importPathwayRecord.TqProviderId); if (existingPathwayRecord != null && existingPathwayRecord.TqRegistrationSpecialisms.Any()) { var existingSpecialisms = existingPathwayRecord.TqRegistrationSpecialisms.Where(s => s.Status == 1).ToList(); //1,1 - 2,1 //3,1 2,1 - 1,1 2,1 //3,1 4,1 - 1,1 2,1 //3,1 4,1 - 1,1 2,1 4,1 // below commented line using EqualityComprarer //var specialismsToAdd = mr.TqSpecialismRegistrations.Except(specialismsInDb, specialismComparer).ToList(); //var specialismsToUpdate = specialismsInDb.Except(mr.TqSpecialismRegistrations, specialismComparer).ToList(); var specialismsToAdd = importPathwayRecord.TqRegistrationSpecialisms.Where(s => !existingSpecialisms.Any(r => r.TlSpecialismId == s.TlSpecialismId)).ToList(); var specialismsToUpdate = existingSpecialisms.Where(s => !importPathwayRecord.TqRegistrationSpecialisms.Any(r => r.TlSpecialismId == s.TlSpecialismId)).ToList(); specialismsToUpdate.ForEach(s => { s.Status = 2; // change the status to inactive or withdrawn s.EndDate = DateTime.UtcNow; s.ModifiedBy = "LoggedIn User"; s.ModifiedOn = DateTime.UtcNow; }); specialismsToAdd.ForEach(s => { s.TqRegistrationPathwayId = existingPathwayRecord.Id; s.Status = 1; s.StartDate = DateTime.UtcNow; s.CreatedBy = "LoggedIn User"; }); if (specialismsToAdd.Count > 0 || specialismsToUpdate.Count > 0) { hasOnlySpecialismsRecordChanged = true; existingPathwayRecord.TqRegistrationSpecialisms.Clear(); existingPathwayRecord.TqRegistrationSpecialisms = specialismsToAdd.Concat(specialismsToUpdate).ToList(); } } else if (existingPathwayRecord != null && importPathwayRecord.TqRegistrationSpecialisms.Any()) { importPathwayRecord.TqRegistrationSpecialisms.ToList().ForEach(s => { existingPathwayRecord.TqRegistrationSpecialisms.Add(new TqRegistrationSpecialism { TqRegistrationPathwayId = existingPathwayRecord.Id, TlSpecialismId = s.TlSpecialismId, StartDate = s.StartDate, Status = s.Status, CreatedBy = s.CreatedBy }); }); hasOnlySpecialismsRecordChanged = true; } }); } } } if (!result.HasAnyErrors) { if (hasTqRegistrationProfileRecordChanged && hasBothPathwayAndSpecialismsRecordsChanged) { modifiedRegistration.TqRegistrationPathways = pathwaysToAdd.Concat(pathwaysToUpdate).ToList(); } else if (hasTqRegistrationProfileRecordChanged && !hasBothPathwayAndSpecialismsRecordsChanged && hasOnlySpecialismsRecordChanged) { pathwaysToUpdate.ForEach(p => { modifiedSpecialismRecords.AddRange(p.TqRegistrationSpecialisms); }); modifiedRegistration.TqRegistrationPathways.Clear(); } else if (hasTqRegistrationProfileRecordChanged && !hasBothPathwayAndSpecialismsRecordsChanged && !hasOnlySpecialismsRecordChanged) { modifiedRegistration.TqRegistrationPathways.Clear(); } else if (hasBothPathwayAndSpecialismsRecordsChanged && !hasOnlySpecialismsRecordChanged) { modifiedPathwayRecords.AddRange(pathwaysToAdd.Concat(pathwaysToUpdate)); modifiedRegistrationsToIgnore.Add(modifiedRegistration); } else if (!hasBothPathwayAndSpecialismsRecordsChanged && hasOnlySpecialismsRecordChanged) { pathwaysToUpdate.ForEach(p => { modifiedSpecialismRecords.AddRange(p.TqRegistrationSpecialisms); }); modifiedRegistrationsToIgnore.Add(modifiedRegistration); } } } }); } if (!result.HasAnyErrors && (newRegistrations.Count > 0 || modifiedRegistrations.Count > 0)) { var registrationsToSendToDB = newRegistrations.Concat(modifiedRegistrations.Except(modifiedRegistrationsToIgnore, ulnComparer)).ToList(); result.IsSuccess = await _registrationRepository.BulkInsertOrUpdateTqRegistrations(registrationsToSendToDB, modifiedPathwayRecords, modifiedSpecialismRecords); result.BulkUploadStats = new BulkUploadStats { NewRecordsCount = newRegistrations.Count, UpdatedRecordsCount = modifiedRegistrations.Count, DuplicateRecordsCount = sameOrDuplicateRegistrations.Count }; } //watch.Stop(); //var sec = watch.ElapsedMilliseconds; return(result); }