internal CerebelloEntitiesAccessFilterWrapper InitDb() { // this is because of how tests work // if a test controller has been created, this.db has already been populated // otherwise let's create a regular one return this.db ?? (this.db = new CerebelloEntitiesAccessFilterWrapper(this.CreateNewCerebelloEntities())); }
internal CerebelloEntitiesAccessFilterWrapper InitDb() { // this is because of how tests work // if a test controller has been created, this.db has already been populated // otherwise let's create a regular one return(this.db ?? (this.db = new CerebelloEntitiesAccessFilterWrapper(this.CreateNewCerebelloEntities()))); }
public static void DeleteFileByMetadata(FileMetadata metadata, CerebelloEntitiesAccessFilterWrapper db, IBlobStorageManager storage) { // deleting dependent files var relatedFiles = db.FileMetadatas.Where(f => f.RelatedFileMetadataId == metadata.Id).ToList(); foreach (var relatedFile in relatedFiles) { DeleteFileByMetadata(relatedFile, db, storage); } // deleting file metadata and storage entries storage.DeleteFileFromStorage(metadata.ContainerName, metadata.BlobName); db.FileMetadatas.DeleteObject(metadata); }
public static List<DoctorViewModel> GetDoctorViewModelsFromPractice(CerebelloEntitiesAccessFilterWrapper db, Practice practice, DateTime localNow) { var usersThatAreDoctors = db.Users .Where(u => u.PracticeId == practice.Id) .Where(u => u.Doctor != null); var dataCollection = usersThatAreDoctors .Select(u => new { ViewModel = new DoctorViewModel() { Id = u.Id, Name = u.Person.FullName, UrlIdentifier = u.Doctor.UrlIdentifier, CRM = u.Doctor.CRM, MedicalSpecialty = u.Doctor.MedicalSpecialtyName, }, u.Doctor.MedicalEntityCode, u.Doctor.MedicalEntityJurisdiction, u.Doctor, u.Person.EmailGravatarHash, }) .ToList(); // Getting more doctor's informations: // Todo: this is going to become a problem in the future, because this info has no cache. // - next free time slot of each doctor; // - gravatar image. foreach (var eachItem in dataCollection) { if (!string.IsNullOrEmpty(eachItem.EmailGravatarHash)) eachItem.ViewModel.ImageUrl = GravatarHelper.GetGravatarUrl(eachItem.EmailGravatarHash, GravatarHelper.Size.s16); eachItem.ViewModel.MedicalEntity = string.Format( string.IsNullOrEmpty(eachItem.MedicalEntityJurisdiction) ? "{0}" : "{0}-{1}", eachItem.MedicalEntityCode, eachItem.MedicalEntityJurisdiction); // It is only possible to determine the next available time if the schedule of the doctor is already configured. if (eachItem.Doctor.CFG_Schedule != null) { var nextSlotInLocalTime = ScheduleController.FindNextFreeTimeInPracticeLocalTime(db, eachItem.Doctor, localNow); eachItem.ViewModel.NextAvailableTime = nextSlotInLocalTime.Item1; } } var doctors = dataCollection.Select(item => item.ViewModel).ToList(); return doctors; }
private static bool ValidateTime( CerebelloEntitiesAccessFilterWrapper db, Doctor doctor, DateTime localDate, string startTimeText, string endTimeText, ModelStateDictionary modelState, ModelStateDictionary inconsistencyMessages, DateTime localNow) { if (string.IsNullOrEmpty(startTimeText) || string.IsNullOrEmpty(endTimeText)) return false; var hasError = false; var startRegexMatch = TimeDataTypeAttribute.Regex.Match(startTimeText); var endRegexMatch = TimeDataTypeAttribute.Regex.Match(endTimeText); var integerHourStart = int.Parse(startRegexMatch.Groups[1].Value) * 100 + int.Parse(startRegexMatch.Groups[2].Value); var integerHourEnd = int.Parse(endRegexMatch.Groups[1].Value) * 100 + int.Parse(endRegexMatch.Groups[2].Value); var monthAndDay = localDate.Month * 100 + localDate.Day; // Validation: cannot be holliday. var isHolliday = db.SYS_Holiday.Any(h => h.MonthAndDay == monthAndDay); if (isHolliday) { inconsistencyMessages.AddModelError<AppointmentViewModel>( model => model.LocalDateTime, "O campo '{0}' é inválido. Este dia é um feriado."); hasError = true; } //var doctor = this.Doctor; // Validation: cannot be day-off. var isDayOff = db.CFG_DayOff .Where(d => d.DoctorId == doctor.Id).Any(d => d.Date == localDate.Date); if (isDayOff) { inconsistencyMessages.AddModelError<AppointmentViewModel>( model => model.LocalDateTime, "O campo '{0}' é inválido. Este dia está no intervalo de dias sem expediente do médico."); hasError = true; } // Validation: cannot set an appointment date to the past. var localStartDate = localDate.Date + DateTimeHelper.GetTimeSpan(startTimeText); if (localStartDate < localNow) { inconsistencyMessages.AddModelError<AppointmentViewModel>( model => model.LocalDateTime, "A data e hora indicadas estão no passado."); hasError = true; } // Validation: end time cannot be the same as start time. if (integerHourStart == integerHourEnd) { modelState.AddModelError<AppointmentViewModel>( model => model.End, "O campo '{0}' não pode ser igual ao horário de início."); hasError = true; } // Validation: end time must come after the start time. else if (integerHourStart > integerHourEnd) { modelState.AddModelError<AppointmentViewModel>( model => model.End, "O campo '{0}' não pode ser menor que o horário de início."); hasError = true; } Action<string, string, string, string> checkModelTimingError = (workdayStart, workdayEnd, lunchStart, lunchEnd) => { if (string.IsNullOrEmpty(workdayStart) || string.IsNullOrEmpty(workdayEnd)) { modelState.AddModelError<AppointmentViewModel>( model => model.LocalDateTime, "O campo '{0}' é inválido. Não existem configurações de horário para esta data."); hasError = true; } else { // Verify the lunch time. // lunch time can only be a problem when it's set, because it's optional // when the start time is set, so it is the end time // I'm checking both here but it could be just one if (!string.IsNullOrEmpty(lunchStart) && !string.IsNullOrEmpty(lunchEnd)) { var lunchStartInteger = GetTimeAsInteger(lunchStart); var lunchEndInteger = GetTimeAsInteger(lunchEnd); bool lunchIsAfter = integerHourStart < lunchStartInteger && integerHourEnd <= lunchStartInteger; bool lunchIsBefore = integerHourStart >= lunchEndInteger && integerHourEnd > lunchEndInteger; if (lunchIsAfter == lunchIsBefore) { inconsistencyMessages.AddModelError<AppointmentViewModel>( model => model.LocalDateTime, "A data e hora marcada está no horário de almoço do médico."); hasError = true; } } // Verify the work time. { var workdayStartInteger = GetTimeAsInteger(workdayStart); var workdayEndInteger = GetTimeAsInteger(workdayEnd); if (integerHourStart < workdayStartInteger) { modelState.AddModelError<AppointmentViewModel>( model => model.Start, "O campo '{0}' não é um horário válido devido às configurações de horário de trabalho."); hasError = true; } if (integerHourEnd > workdayEndInteger) { modelState.AddModelError<AppointmentViewModel>( model => model.End, "O campo '{0}' não é um horário válido devido às configurações de horário de trabalho."); hasError = true; } } } }; switch (localDate.Date.DayOfWeek) { case DayOfWeek.Sunday: checkModelTimingError( doctor.CFG_Schedule.SundayWorkdayStartTime, doctor.CFG_Schedule.SundayWorkdayEndTime, doctor.CFG_Schedule.SundayLunchStartTime, doctor.CFG_Schedule.SundayLunchEndTime); break; case DayOfWeek.Monday: checkModelTimingError( doctor.CFG_Schedule.MondayWorkdayStartTime, doctor.CFG_Schedule.MondayWorkdayEndTime, doctor.CFG_Schedule.MondayLunchStartTime, doctor.CFG_Schedule.MondayLunchEndTime); break; case DayOfWeek.Tuesday: checkModelTimingError( doctor.CFG_Schedule.TuesdayWorkdayStartTime, doctor.CFG_Schedule.TuesdayWorkdayEndTime, doctor.CFG_Schedule.TuesdayLunchStartTime, doctor.CFG_Schedule.TuesdayLunchEndTime); break; case DayOfWeek.Wednesday: checkModelTimingError( doctor.CFG_Schedule.WednesdayWorkdayStartTime, doctor.CFG_Schedule.WednesdayWorkdayEndTime, doctor.CFG_Schedule.WednesdayLunchStartTime, doctor.CFG_Schedule.WednesdayLunchEndTime); break; case DayOfWeek.Thursday: checkModelTimingError( doctor.CFG_Schedule.ThursdayWorkdayStartTime, doctor.CFG_Schedule.ThursdayWorkdayEndTime, doctor.CFG_Schedule.ThursdayLunchStartTime, doctor.CFG_Schedule.ThursdayLunchEndTime); break; case DayOfWeek.Friday: checkModelTimingError( doctor.CFG_Schedule.FridayWorkdayStartTime, doctor.CFG_Schedule.FridayWorkdayEndTime, doctor.CFG_Schedule.FridayLunchStartTime, doctor.CFG_Schedule.FridayLunchEndTime); break; case DayOfWeek.Saturday: checkModelTimingError( doctor.CFG_Schedule.SaturdayWorkdayStartTime, doctor.CFG_Schedule.SaturdayWorkdayEndTime, doctor.CFG_Schedule.SaturdayLunchStartTime, doctor.CFG_Schedule.SaturdayLunchEndTime); break; } return !hasError; }
/// <summary> /// Returns the next free time of a doctor, in local practice time-zone. /// </summary> /// <param name="db"></param> /// <param name="doctor"></param> /// <param name="startingFromLocalTime"> /// The date and time to start scanning for free times. /// This must be a time in the practice time-zone. /// </param> /// <returns></returns> public static Tuple<DateTime, DateTime> FindNextFreeTimeInPracticeLocalTime( CerebelloEntitiesAccessFilterWrapper db, Doctor doctor, DateTime startingFromLocalTime) { if (startingFromLocalTime.Kind != DateTimeKind.Unspecified) throw new ArgumentException("'startingFromLocalTime' must be expressed in local practice time-zone.", "startingFromLocalTime"); var practice = doctor.Users.FirstOrDefault().Practice; var currentDateStartLocal = startingFromLocalTime.Date; while (true) { // getting a list of valid dates to look for slots // - days-off are invalid DateTime[] validLocalDates; { var currentDateEndLocal = currentDateStartLocal.AddDays(30.0); while (true) { var daysOffDates = db.CFG_DayOff .Where(df => df.DoctorId == doctor.Id) .Where(df => df.Date >= currentDateStartLocal && df.Date < currentDateEndLocal) .Select(df => df.Date) .ToArray(); validLocalDates = DateTimeHelper.Range(currentDateStartLocal, 30, d => d.AddDays(1.0)).ToArray(); validLocalDates = validLocalDates.Except(daysOffDates).ToArray(); if (validLocalDates.Length > 0) break; currentDateStartLocal = currentDateEndLocal; } } // For each valid date, we look inside them for available slots. foreach (var eachValidLocalDate in validLocalDates) { var currentDateStartUtc = ConvertToUtcDateTime(practice, eachValidLocalDate); var currentDateEndUtc = ConvertToUtcDateTime(practice, eachValidLocalDate.AddDays(1.0).AddTicks(-1)); // take all appointments of that day var appointments = db.Appointments .Where(a => a.DoctorId == doctor.Id) .Where(a => a.End >= currentDateStartUtc && a.Start <= currentDateEndUtc) .OrderBy(a => a.Start) .ToList(); var slots = GetDaySlotsInLocalTime(eachValidLocalDate, doctor) .Where(s => s.Item1 >= startingFromLocalTime) .Select(s => new { StartUtc = ConvertToUtcDateTime(practice, s.Item1), EndUtc = ConvertToUtcDateTime(practice, s.Item2) }) .ToList(); // Looking for available slots of time in the current day. foreach (var slot in slots) { if (!IsTimeAvailableUtc(slot.StartUtc, slot.EndUtc, appointments)) continue; return Tuple.Create( ConvertToLocalDateTime(practice, slot.StartUtc), ConvertToLocalDateTime(practice, slot.EndUtc)); }; } } }
public DbFileMetadataProvider(CerebelloEntitiesAccessFilterWrapper db, IDateTimeService dateTimeService, int practiceId) { this.db = db; this.dateTimeService = dateTimeService; this.practiceId = practiceId; }
public static void BackupEverything([NotNull] CerebelloEntities db, List <string> errors = null) { if (db == null) { throw new ArgumentNullException("db"); } if (errors == null) { errors = new List <string>(); } using (db) { var dbWrapper = new CerebelloEntitiesAccessFilterWrapper(db); var patientsToBackup = db.Patients.Where(p => p.Doctor.Users.Any(u => u.Person.GoogleUserAccoutInfoes.Any()) && !p.IsBackedUp).GroupBy(p => p.DoctorId); foreach (var patientGroup in patientsToBackup.ToList()) { try { var doctor = db.Doctors.First(d => d.Id == patientGroup.Key); dbWrapper.SetCurrentUserById(doctor.Users.First().Id); var doctorGoogleAccountInfo = doctor.Users.First().Person.GoogleUserAccoutInfoes.FirstOrDefault(); if (doctorGoogleAccountInfo != null) { // in this case the doctor for these patients have a Google Account associated var requestAccessResult = GoogleApiHelper.RequestAccessToken(doctorGoogleAccountInfo.RefreshToken); var authenticator = GoogleApiHelper.GetAuthenticator( doctorGoogleAccountInfo.RefreshToken, requestAccessResult.access_token); var driveService = new DriveService(authenticator); // create Cerebello folder if it does not exist var practiceGoogleDriveInfo = doctor.Practice.GoogleDrivePracticeInfoes.FirstOrDefault(); File cerebelloFolder = null; if (practiceGoogleDriveInfo != null) { try { cerebelloFolder = GoogleApiHelper.GetFile(driveService, practiceGoogleDriveInfo.CerebelloFolderId); if (cerebelloFolder.Labels.Trashed.HasValue && cerebelloFolder.Labels.Trashed.Value) { cerebelloFolder = null; } } catch (Exception ex) { var errorMessage = "Error downloading file from Google Drive. Exception message: " + ex.Message; // the f*****g user deleted the f*****g folder OR something went wrong downloading the file Trace.TraceError("BackupHelper.BackupEverything(db, errors): " + errorMessage); errors.Add(errorMessage); } } if (cerebelloFolder == null) { cerebelloFolder = GoogleApiHelper.CreateFolder(driveService, "Cerebello", "Pasta do Cerebello"); if (practiceGoogleDriveInfo != null) { practiceGoogleDriveInfo.CerebelloFolderId = cerebelloFolder.Id; } else { practiceGoogleDriveInfo = new GoogleDrivePracticeInfo() { CerebelloFolderId = cerebelloFolder.Id, PracticeId = doctor.PracticeId }; doctor.Practice.GoogleDrivePracticeInfoes.Add(practiceGoogleDriveInfo); } db.SaveChanges(); } foreach (var patient in patientGroup) { try { var patientBackup = GeneratePatientBackup(dbWrapper, patient); var fileName = string.Format("{0} (id:{1})", patient.Person.FullName, patient.Id) + ".zip"; var fileDescription = string.Format( "Arquivo de backup do(a) paciente {0} (id:{1})", patient.Person.FullName, patient.Id); // check if the file exists already var patientGoogleDriveFile = patient.GoogleDrivePatientInfoes.FirstOrDefault(); File googleDrivePatientFile = null; if (patientGoogleDriveFile != null) { try { // get reference to existing file to make sure it exists var existingFile = GoogleApiHelper.GetFile( driveService, patientGoogleDriveFile.PatientBackupFileId); if (!existingFile.Labels.Trashed.HasValue || !existingFile.Labels.Trashed.Value) { googleDrivePatientFile = GoogleApiHelper.UpdateFile( driveService, patientGoogleDriveFile.PatientBackupFileId, fileName, fileDescription, MimeTypesHelper.GetContentType(".zip"), patientBackup); if (googleDrivePatientFile.Labels.Trashed.HasValue && googleDrivePatientFile.Labels.Trashed.Value) { googleDrivePatientFile = null; } } } catch (Exception ex) { var errorMessage = "Error updating file from Google Drive. Exception message: " + ex.Message; // the f*****g user deleted the f*****g folder OR something went wrong downloading the file Trace.TraceError("BackupHelper.BackupEverything(db, errors): " + errorMessage); errors.Add(errorMessage); } } if (googleDrivePatientFile == null) { googleDrivePatientFile = GoogleApiHelper.CreateFile( driveService, fileName, fileDescription, MimeTypesHelper.GetContentType(".zip"), patientBackup, new List <ParentReference>() { new ParentReference() { Id = cerebelloFolder.Id } }); if (patientGoogleDriveFile != null) { patientGoogleDriveFile.PatientBackupFileId = googleDrivePatientFile.Id; } else { patient.GoogleDrivePatientInfoes.Add( new GoogleDrivePatientInfo() { PatientBackupFileId = googleDrivePatientFile.Id, PracticeId = doctor.PracticeId }); } } patient.IsBackedUp = true; db.SaveChanges(); } catch (Exception ex) { var errorMessage = "Error synchronizing files for a specific doctor. Exception message" + ex.Message; // the f*****g user deleted the f*****g folder OR something went wrong downloading the file Trace.TraceError("BackupHelper.BackupEverything(db, errors): " + errorMessage); errors.Add(errorMessage); } } } } catch (Exception ex) { var errorMessage = "Error synchronizing files. Exception message" + ex.Message; // the f*****g user deleted the f*****g folder OR something went wrong downloading the file Trace.TraceError("BackupHelper.BackupEverything(db, errors): " + errorMessage); errors.Add(errorMessage); } } } }
public static MemoryStream GeneratePatientBackup([NotNull] CerebelloEntitiesAccessFilterWrapper db, [NotNull] Patient patient) { if (db == null) { throw new ArgumentNullException("db"); } if (patient == null) { throw new ArgumentNullException("patient"); } var zipMemoryStream = new MemoryStream(); using (var patientZip = new ZipFile()) { var storageManager = new WindowsAzureBlobStorageManager(); // add the patient history as pdf var pdf = ReportController.ExportPatientsPdf(patient.Id, db, patient.Practice, patient.Doctor); patientZip.AddEntry(string.Format("{0} - Histórico.pdf", patient.Person.FullName), pdf); // if the person has a picture, add it to the backup if (patient.Person.PictureBlobName != null) { var picture = storageManager.DownloadFileFromStorage(Constants.PERSON_PROFILE_PICTURE_CONTAINER_NAME, patient.Person.PictureBlobName); patientZip.AddEntry(string.Format("{0} - Perfil.png", patient.Person.FullName), picture); } // if the person has files, add them to the backup var patientFiles = db.PatientFiles.Where(pf => pf.PatientId == patient.Id).ToList(); if (patientFiles.Any()) { using (var patientFilesZip = new ZipFile()) { var patientFilesZipMemoryStream = new MemoryStream(); foreach (var patientFile in patientFiles) { var fileStream = storageManager.DownloadFileFromStorage( patientFile.FileMetadata.ContainerName, patientFile.FileMetadata.BlobName); var fileName = patientFile.FileMetadata.SourceFileName; for (var i = 2;; i++) { if (patientFilesZip.ContainsEntry(fileName)) { fileName = Path.GetFileNameWithoutExtension(fileName) + " " + i + Path.GetExtension(fileName); } else { break; } } patientFilesZip.AddEntry(fileName, fileStream); } patientFilesZip.Save(patientFilesZipMemoryStream); patientFilesZipMemoryStream.Seek(0, SeekOrigin.Begin); patientZip.AddEntry(string.Format("{0} - Arquivos.zip", patient.Person.FullName), patientFilesZipMemoryStream); } } patientZip.Save(zipMemoryStream); } zipMemoryStream.Seek(0, SeekOrigin.Begin); return(zipMemoryStream); }
public void Create_SaveAppointmentWhenStatusIsSetForTheFuture_NotAccomplished() { ScheduleController controller; AppointmentViewModel vm; try { // Creating practice, doctor and patient. var docAndre = Firestarter.Create_CrmMg_Psiquiatria_DrHouse_Andre(this.db); Firestarter.SetupDoctor(docAndre, this.db); var patient = Firestarter.CreateFakePatients(docAndre, this.db, 1)[0]; patient.LastUsedHealthInsuranceId = null; this.db.SaveChanges(); var timeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById(docAndre.Users.Single().Practice.WindowsTimeZoneId); var localNow = new DateTime(2012, 11, 09, 13, 00, 00, 000); var utcNow = TimeZoneInfo.ConvertTimeToUtc(localNow, timeZoneInfo); // the next free time from "now" var db2 = new CerebelloEntitiesAccessFilterWrapper(this.db); db2.SetCurrentUserById(docAndre.Users.Single().Id); // the reason for this .AddMinutes(1) is that FindNextFreeTimeInPracticeLocalTime returns now, when now is available // but now is not considered future, and I need a date in the future so the Status validation will fail var nextFreeTime = ScheduleController.FindNextFreeTimeInPracticeLocalTime(db2, docAndre, localNow.AddMinutes(1)); // Creating Asp.Net Mvc mocks. var mr = new MockRepository(true); mr.SetRouteData_ConsultorioDrHouse_GregoryHouse(typeof(ScheduleController), "Create"); controller = mr.CreateController<ScheduleController>(); // Mocking 'Now' values. controller.UtcNowGetter = () => utcNow; // Setting view-model values to create a new appointment. vm = new AppointmentViewModel { PatientId = patient.Id, PatientNameLookup = patient.Person.FullName, HealthInsuranceId = docAndre.HealthInsurances.First(hi => hi.IsActive).Id, LocalDateTime = nextFreeTime.Item1.Date, DoctorId = docAndre.Id, Start = nextFreeTime.Item1.ToString("HH:mm"), End = nextFreeTime.Item2.ToString("HH:mm"), IsGenericAppointment = false, // this has to generate an error because the appointment is in the future Status = (int)TypeAppointmentStatus.NotAccomplished, }; Mvc3TestHelper.SetModelStateErrors(controller, vm); } catch (Exception ex) { InconclusiveInit(ex); return; } var result = controller.Create(vm); Assert.IsFalse(controller.ModelState.IsValid); Assert.AreEqual(1, controller.ModelState["Status"].Errors.Count); }
public void Create_SaveAppointmentWhenStatusIsSetForThePast_NotAccomplished() { ScheduleController controller; AppointmentViewModel vm; try { // Creating practice, doctor and patient. var docAndre = Firestarter.Create_CrmMg_Psiquiatria_DrHouse_Andre(this.db); Firestarter.SetupDoctor(docAndre, this.db); var patient = Firestarter.CreateFakePatients(docAndre, this.db, 1)[0]; patient.LastUsedHealthInsuranceId = null; this.db.SaveChanges(); var timeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById(docAndre.Users.Single().Practice.WindowsTimeZoneId); var localNow = new DateTime(2012, 11, 09, 13, 00, 00, 000); var utcNow = TimeZoneInfo.ConvertTimeToUtc(localNow, timeZoneInfo); // finds a free time in the past week. var db2 = new CerebelloEntitiesAccessFilterWrapper(this.db); db2.SetCurrentUserById(docAndre.Users.Single().Id); var freeTimeInPastWeek = ScheduleController.FindNextFreeTimeInPracticeLocalTime(db2, docAndre, localNow.AddDays(-7)); // Creating Asp.Net Mvc mocks. var mr = new MockRepository(true); mr.SetRouteData_ConsultorioDrHouse_GregoryHouse(typeof(ScheduleController), "Create"); controller = mr.CreateController<ScheduleController>(); // Mocking 'Now' values. controller.UtcNowGetter = () => utcNow; // Setting view-model values to create a new appointment. vm = new AppointmentViewModel { PatientId = patient.Id, PatientNameLookup = patient.Person.FullName, HealthInsuranceId = docAndre.HealthInsurances.First(hi => hi.IsActive).Id, LocalDateTime = freeTimeInPastWeek.Item1.Date, DoctorId = docAndre.Id, Start = freeTimeInPastWeek.Item1.ToString("HH:mm"), End = freeTimeInPastWeek.Item2.ToString("HH:mm"), IsGenericAppointment = false, // this should work because it's in the past Status = (int)TypeAppointmentStatus.NotAccomplished, }; Mvc3TestHelper.SetModelStateErrors(controller, vm); } catch (Exception ex) { InconclusiveInit(ex); return; } controller.Create(vm); Assert.IsTrue(controller.ModelState.IsValid); }
public static void BackupEverything([NotNull] CerebelloEntities db, List<string> errors = null) { if (db == null) throw new ArgumentNullException("db"); if(errors == null) errors =new List<string>(); using (db) { var dbWrapper = new CerebelloEntitiesAccessFilterWrapper(db); var patientsToBackup = db.Patients.Where(p => p.Doctor.Users.Any(u => u.Person.GoogleUserAccoutInfoes.Any()) && !p.IsBackedUp).GroupBy(p => p.DoctorId); foreach (var patientGroup in patientsToBackup.ToList()) { try { var doctor = db.Doctors.First(d => d.Id == patientGroup.Key); dbWrapper.SetCurrentUserById(doctor.Users.First().Id); var doctorGoogleAccountInfo = doctor.Users.First().Person.GoogleUserAccoutInfoes.FirstOrDefault(); if (doctorGoogleAccountInfo != null) { // in this case the doctor for these patients have a Google Account associated var requestAccessResult = GoogleApiHelper.RequestAccessToken(doctorGoogleAccountInfo.RefreshToken); var authenticator = GoogleApiHelper.GetAuthenticator( doctorGoogleAccountInfo.RefreshToken, requestAccessResult.access_token); var driveService = new DriveService(authenticator); // create Cerebello folder if it does not exist var practiceGoogleDriveInfo = doctor.Practice.GoogleDrivePracticeInfoes.FirstOrDefault(); File cerebelloFolder = null; if (practiceGoogleDriveInfo != null) { try { cerebelloFolder = GoogleApiHelper.GetFile(driveService, practiceGoogleDriveInfo.CerebelloFolderId); if (cerebelloFolder.Labels.Trashed.HasValue && cerebelloFolder.Labels.Trashed.Value) cerebelloFolder = null; } catch (Exception ex) { var errorMessage = "Error downloading file from Google Drive. Exception message: " + ex.Message; // the f*****g user deleted the f*****g folder OR something went wrong downloading the file Trace.TraceError("BackupHelper.BackupEverything(db, errors): " + errorMessage); errors.Add(errorMessage); } } if (cerebelloFolder == null) { cerebelloFolder = GoogleApiHelper.CreateFolder(driveService, "Cerebello", "Pasta do Cerebello"); if (practiceGoogleDriveInfo != null) practiceGoogleDriveInfo.CerebelloFolderId = cerebelloFolder.Id; else { practiceGoogleDriveInfo = new GoogleDrivePracticeInfo() { CerebelloFolderId = cerebelloFolder.Id, PracticeId = doctor.PracticeId }; doctor.Practice.GoogleDrivePracticeInfoes.Add(practiceGoogleDriveInfo); } db.SaveChanges(); } foreach (var patient in patientGroup) { try { var patientBackup = GeneratePatientBackup(dbWrapper, patient); var fileName = string.Format("{0} (id:{1})", patient.Person.FullName, patient.Id) + ".zip"; var fileDescription = string.Format( "Arquivo de backup do(a) paciente {0} (id:{1})", patient.Person.FullName, patient.Id); // check if the file exists already var patientGoogleDriveFile = patient.GoogleDrivePatientInfoes.FirstOrDefault(); File googleDrivePatientFile = null; if (patientGoogleDriveFile != null) { try { // get reference to existing file to make sure it exists var existingFile = GoogleApiHelper.GetFile( driveService, patientGoogleDriveFile.PatientBackupFileId); if (!existingFile.Labels.Trashed.HasValue || !existingFile.Labels.Trashed.Value) { googleDrivePatientFile = GoogleApiHelper.UpdateFile( driveService, patientGoogleDriveFile.PatientBackupFileId, fileName, fileDescription, MimeTypesHelper.GetContentType(".zip"), patientBackup); if (googleDrivePatientFile.Labels.Trashed.HasValue && googleDrivePatientFile.Labels.Trashed.Value) googleDrivePatientFile = null; } } catch (Exception ex) { var errorMessage = "Error updating file from Google Drive. Exception message: " + ex.Message; // the f*****g user deleted the f*****g folder OR something went wrong downloading the file Trace.TraceError("BackupHelper.BackupEverything(db, errors): " + errorMessage); errors.Add(errorMessage); } } if (googleDrivePatientFile == null) { googleDrivePatientFile = GoogleApiHelper.CreateFile( driveService, fileName, fileDescription, MimeTypesHelper.GetContentType(".zip"), patientBackup, new List<ParentReference>() { new ParentReference() { Id = cerebelloFolder.Id } }); if (patientGoogleDriveFile != null) patientGoogleDriveFile.PatientBackupFileId = googleDrivePatientFile.Id; else { patient.GoogleDrivePatientInfoes.Add( new GoogleDrivePatientInfo() { PatientBackupFileId = googleDrivePatientFile.Id, PracticeId = doctor.PracticeId }); } } patient.IsBackedUp = true; db.SaveChanges(); } catch (Exception ex) { var errorMessage = "Error synchronizing files for a specific doctor. Exception message" + ex.Message; // the f*****g user deleted the f*****g folder OR something went wrong downloading the file Trace.TraceError("BackupHelper.BackupEverything(db, errors): " + errorMessage); errors.Add(errorMessage); } } } } catch (Exception ex) { var errorMessage = "Error synchronizing files. Exception message" + ex.Message; // the f*****g user deleted the f*****g folder OR something went wrong downloading the file Trace.TraceError("BackupHelper.BackupEverything(db, errors): " + errorMessage); errors.Add(errorMessage); } } } }