public static void Sync(ConfigFile configFile, LogDelegate Log) { ConfigFileSyncPermissionsSection config = configFile.StudentGradePlacementPermissions; Log("========= GRADE PLACEMENTS FOR " + configFile.SchoolYearName + " ========= "); if (!config.AllowSync) { Log("This sync module is disabled in config file - skipping"); return; } // Parse the school year from the config file, we'll need it later InternalSchoolYearRepository _schoolYearRepo = new InternalSchoolYearRepository(configFile.DatabaseConnectionString_Internal); SchoolYear schoolYear = _schoolYearRepo.Get(configFile.SchoolYearName); if (schoolYear == null) { throw new InvalidSchoolYearException("School year from config file is invalid"); } InternalGradePlacementRepository internalRepository = new InternalGradePlacementRepository(configFile.DatabaseConnectionString_Internal); SLGradePlacementRepository externalRepository = new SLGradePlacementRepository(configFile.DatabaseConnectionString_SchoolLogic, schoolYear); // This one is handled differently than other syncs List <StudentGradePlacement> externalObjects = externalRepository.GetAll(); Log("Found " + internalRepository.GetAllForSchoolYear(schoolYear.ID).Count() + " placements in internal database for this school year"); Log("Found " + externalObjects.Count() + " placements in external database"); // Find previously unknown schools // Find schools that need an update List <StudentGradePlacement> previouslyUnknown = new List <StudentGradePlacement>(); List <StudentGradePlacement> needingUpdate = new List <StudentGradePlacement>(); List <StudentGradePlacement> noLongerExistsInExternalSystem = new List <StudentGradePlacement>(); int doneCount = 0; int totalExternalObjects = externalObjects.Count(); decimal donePercent = 0; decimal doneThresholdPercent = (decimal)0.1; decimal doneThresholdIncrease = (decimal)0.1; foreach (StudentGradePlacement externalObject in externalObjects) { // Check to see if we know about this object already StudentGradePlacement internalObject = internalRepository.Get(schoolYear, externalObject.iStudentID); if (internalObject == null) { previouslyUnknown.Add(externalObject); } // Check to see if this school requires an update if (internalObject != null) { UpdateCheck check = internalObject.CheckIfUpdatesAreRequired(externalObject); if ((check == UpdateCheck.UpdatesRequired) || (config.ForceUpdate)) { needingUpdate.Add(externalObject); } } doneCount++; donePercent = (decimal)((decimal)doneCount / (decimal)totalExternalObjects); if (donePercent > doneThresholdPercent) { doneThresholdPercent = doneThresholdPercent + doneThresholdIncrease; Log((int)(donePercent * 100) + "% finished inspecting objects"); } if (doneCount == totalExternalObjects) { Log("100% finished inspecting objects"); } } Log("Found " + previouslyUnknown.Count() + " previously unknown"); Log("Found " + needingUpdate.Count() + " with updates"); // Commit these changes to the database if (previouslyUnknown.Count > 0) { if (config.AllowAdds) { Log(" > Adding " + previouslyUnknown.Count() + " new objects"); internalRepository.Add(previouslyUnknown); } else { Log(" > Not allowed to add, skipping " + previouslyUnknown.Count() + " adds"); } } if (needingUpdate.Count > 0) { if (config.AllowUpdates) { Log(" > Updating " + needingUpdate.Count() + " objects"); internalRepository.Update(needingUpdate); } else { Log(" > Not allowed to do updates, skipping " + needingUpdate.Count() + " updates"); } } if (noLongerExistsInExternalSystem.Count > 0) { if (config.AllowRemovals) { Log(" > If removals were implemented, we would remove " + noLongerExistsInExternalSystem.Count() + " objects here"); } else { Log(" > Not allowed to remove, skipping " + noLongerExistsInExternalSystem.Count() + " removals"); } } }
public static void Sync(ConfigFile configFile, LogDelegate Log) { ConfigFileSyncPermissionsSection config = configFile.AbsencePermissions; Log("========= ABSENCES ========= "); if (!config.AllowSync) { Log("This sync module is disabled in config file - skipping"); return; } // Parse the school year from the config file, we'll need it later InternalSchoolYearRepository _schoolYearRepo = new InternalSchoolYearRepository(configFile.DatabaseConnectionString_Internal); SchoolYear schoolYear = _schoolYearRepo.Get(configFile.SchoolYearName); if (schoolYear == null) { throw new InvalidSchoolYearException("School year from config file is invalid"); } SLAbsenceRepository externalRepository = new SLAbsenceRepository(configFile.DatabaseConnectionString_SchoolLogic, schoolYear); InternalAbsenceRepository internalRepository = new InternalAbsenceRepository(configFile.DatabaseConnectionString_Internal); List <Absence> externalObjects = externalRepository.GetAll(); List <Absence> internalObjects = internalRepository.GetForSchoolYear(schoolYear.ID); Log("Found " + internalObjects.Count() + " absences in internal database for this school year"); Log("Found " + externalObjects.Count() + " absences in external database"); // Find previously unknown schools // Find schools that need an update List <Absence> previouslyUnknown = new List <Absence>(); List <Absence> needingUpdate = new List <Absence>(); List <Absence> noLongerExistsInExternalSystem = new List <Absence>(); int doneCount = 0; int totalExternalObjects = externalObjects.Count(); decimal donePercent = 0; decimal doneThresholdPercent = (decimal)0.01; decimal doneThresholdIncrease = (decimal)0.01; foreach (Absence externalObject in externalObjects) { // Check to see if we know about this school already Absence internalObject = internalObjects.GetWithID(externalObject.ID); if (internalObject == null) { previouslyUnknown.Add(externalObject); } // Check to see if this school requires an update if (internalObject != null) { UpdateCheck check = internalObject.CheckIfUpdatesAreRequired(externalObject); if ((check == UpdateCheck.UpdatesRequired) || (config.ForceUpdate)) { needingUpdate.Add(externalObject); } } doneCount++; donePercent = (decimal)((decimal)doneCount / (decimal)totalExternalObjects); if (donePercent > doneThresholdPercent) { doneThresholdPercent = doneThresholdPercent + doneThresholdIncrease; Log((int)(donePercent * 100) + "% finished inspecting objects"); } if (doneCount == totalExternalObjects) { Log("100% finished inspecting objects"); } } // Find schools that are no longer in the database that could potentially be cleaned up if (config.AllowRemovals) { List <int> foundIDs = externalRepository.GetAllIDs(); foreach (Absence internalObject in internalObjects) { if (!foundIDs.Contains(internalObject.ID)) { noLongerExistsInExternalSystem.Add(internalObject); } } } Log("Found " + previouslyUnknown.Count() + " previously unknown"); Log("Found " + needingUpdate.Count() + " with updates"); Log("Found " + noLongerExistsInExternalSystem.Count() + " not in external database"); // Commit these changes to the database if (previouslyUnknown.Count > 0) { if (config.AllowAdds) { Log(" > Adding " + previouslyUnknown.Count() + " new objects"); internalRepository.Add(previouslyUnknown); } else { Log(" > Not allowed to add, skipping " + previouslyUnknown.Count() + " adds"); } } if (needingUpdate.Count > 0) { if (config.AllowUpdates) { Log(" > Updating " + needingUpdate.Count() + " objects"); internalRepository.Update(needingUpdate); } else { Log(" > Not allowed to do updates, skipping " + needingUpdate.Count() + " updates"); } } if (noLongerExistsInExternalSystem.Count > 0) { if (config.AllowRemovals) { Log(" > If removals were implemented, we would remove " + noLongerExistsInExternalSystem.Count() + " objects here"); } else { Log(" > Not allowed to remove, skipping " + noLongerExistsInExternalSystem.Count() + " removals"); } } }
static void Main(string[] args) { try { if (args.Any()) { string configFileName = string.Empty; foreach (string argument in args) { if (argument.ToLower().StartsWith("/config:")) { configFileName = argument.Substring(8, argument.Length - 8); } } if (string.IsNullOrEmpty(configFileName)) { throw new SyntaxException("A config file filename is required"); } // Attempt to load the config file configFile = ConfigFile.LoadFromFile(configFileName); // Validate the config file configFile.Validate(); Log("Data Gatherer started"); // Check to see if the log file folder needs to be created if (!Directory.Exists(configFile.LogDirectory)) { Directory.CreateDirectory(configFile.LogDirectory); } // Parse the working school year InternalSchoolYearRepository schoolYearRepository = new InternalSchoolYearRepository(configFile.DatabaseConnectionString_Internal); SchoolYear schoolYear = schoolYearRepository.Get(configFile.SchoolYearName); if (schoolYear == null) { throw new Exception("Invalid school year in config file: " + configFile.SchoolYearName); } Log("Config file checks OK"); // Display information on what we're allowed to do based on the config file Log("Permissions summary:"); Log("Absences: \t\t\t" + configFile.AbsencePermissions.ToString()); Log("AbsenceStatuses: \t\t" + configFile.AbsenceStatusPermissions.ToString()); Log("AbsenceReasons: \t\t" + configFile.AbsenceReasonPermissions.ToString()); Log("GradeLevels: \t\t\t" + configFile.GradeLevelPermissions.ToString()); Log("Schools: \t\t\t" + configFile.SchoolPermissions.ToString()); Log("StudentGradePlacements: \t" + configFile.StudentGradePlacementPermissions.ToString()); Log("Students: \t\t\t" + configFile.StudentPermissions.ToString()); Log("ExpectedAttendance: \t\t" + configFile.ExpectedAttendancePermissions.ToString()); Log("StudentSchoolEnrolments: \t\t" + configFile.StudentSchoolEnrolmentPermissions.ToString()); LogDelegate logCallback = Log; // Conduct the sync // SCHOOLS SchoolSync.Sync(configFile, logCallback); // GRADE LEVELS GradeLevelSync.Sync(configFile, logCallback); // GRADE PLACEMENTS StudentGradePlacementSync.Sync(configFile, logCallback); // STUDENTS StudentSync.Sync(configFile, logCallback); // ABSENCE REASONS AbsenceReasonSync.Sync(configFile, logCallback); // ABSENCE STATUSES AbsenceStatusSync.Sync(configFile, logCallback); // Absences AbsenceSync.Sync(configFile, logCallback); // STUDENT EXPECTED BLOCKS PER DAY StudentExpectedBlocksSync.Sync(configFile, logCallback); // Student school enrolments StudentSchoolEnrolmentSync.Sync(configFile, logCallback); Log("Data Gatherer complete"); } else { throw new SyntaxException("Not enough arguments"); } } catch (SyntaxException ex) { Console.WriteLine("Error: " + ex.Message); SendSyntax(); } catch (Exception ex) { Console.WriteLine(ex.Message); }// */ }
public static void Sync(ConfigFile configFile, LogDelegate Log) { ConfigFileSyncPermissionsSection config = configFile.ExpectedAttendancePermissions; Log("========= EXPECTED ATTENDANCE ========= "); if (!config.AllowSync) { Log("This sync module is disabled in config file - skipping"); return; } // Load all students that have enrolled classes // - a DISTINCT() on the enrollment table should do nicely here // Load all of those student's schedules // - Load each class's schedule, then combine into the student's own schedule // Parse the school year from the config file, we'll need it later InternalSchoolYearRepository _schoolYearRepo = new InternalSchoolYearRepository(configFile.DatabaseConnectionString_Internal); SchoolYear schoolYear = _schoolYearRepo.Get(configFile.SchoolYearName); if (schoolYear == null) { throw new InvalidSchoolYearException("School year from config file is invalid"); } SLStudentRepository _studentRepo = new SLStudentRepository(configFile.DatabaseConnectionString_SchoolLogic); SLTrackRepository _trackRepo = new SLTrackRepository(configFile.DatabaseConnectionString_SchoolLogic); List <Student> dailyAttendanceStudents = _studentRepo.GetDailyAttendanceStudents(); List <Student> periodAttendanceStudents = _studentRepo.GetPeriodAttendanceStudents(); Log("Found " + dailyAttendanceStudents.Count() + " students in a daily track"); Log("Found " + periodAttendanceStudents.Count() + " students in a period track"); List <StudentExpectedAttendanceEntry> externalObjects = new List <StudentExpectedAttendanceEntry>(); foreach (Student student in dailyAttendanceStudents) { // Get this student's track Track track = _trackRepo.GetTrackFor(student.iStudentID); if (track != null) { // For each calendar day for the whole school year foreach (CalendarDay day in CalendarDay.GetCalendarDaysBetween(schoolYear.Starts, schoolYear.Ends, true)) { // If this calendar day is instructional, use the daily blocks per day for the track as the value // If this calendar day is not instructional, set it to zero // We might not want to actually store zeroes in the database if (track.Schedule.IsInstructional(day)) { externalObjects.Add(new StudentExpectedAttendanceEntry() { iStudentID = student.iStudentID, iSchoolYearID = schoolYear.ID, Date = day, BlocksToday = track.DailyBlocksPerDay }); } } } } // Get student schedules for period attendance students SLStudentScheduleRepository _scheduleRepository = new SLStudentScheduleRepository(configFile.DatabaseConnectionString_SchoolLogic); Log("Loading student schedules..."); Dictionary <int, StudentClassSchedule> _allStudentSchedules = _scheduleRepository.Get(periodAttendanceStudents.Select(x => x.iStudentID).ToList()); Log("Finished loading student schedules."); foreach (Student student in periodAttendanceStudents) { // Get this student's track Track track = _trackRepo.GetTrackFor(student.iStudentID); if (!_allStudentSchedules.ContainsKey(student.iStudentID)) { continue; } StudentClassSchedule schedule = _allStudentSchedules[student.iStudentID]; // Make a StudentSchedule object to handle some of this automatically // I want to create a new StudentSchedule object (or a dictionary of them) // that can be easily queried for a specific calendar day if (track != null) { // For each calendar day for the whole school year foreach (CalendarDay day in CalendarDay.GetCalendarDaysBetween(schoolYear.Starts, schoolYear.Ends, true)) { // If this calendar day is instructional, calculate the student's scheduled blocks if (track.Schedule.IsInstructional(day)) { // Calculate the student's schedule for today int blocksToday = schedule.GetNumberOfScheduledBlocksOn(day); if (blocksToday > 0) { externalObjects.Add(new StudentExpectedAttendanceEntry() { iStudentID = student.iStudentID, iSchoolYearID = schoolYear.ID, Date = day, BlocksToday = blocksToday }); } } } } } Log("Found " + externalObjects.Count() + " external objects"); InternalStudentExpectedAttendanceRepository internalRepository = new InternalStudentExpectedAttendanceRepository(configFile.DatabaseConnectionString_Internal); Log("Found " + internalRepository.RecordCount(schoolYear.ID) + " internal objects"); /* ************************************************************ */ // * // * This took over 6 hours to do, so we need to make a more efficient way of doing this. // * Perhaps the repository needs to store in a Dictionary<> mess instead of a single list // * /* ************************************************************ */ // Compare for changes after here - all the above code was just loading stuff List <StudentExpectedAttendanceEntry> previouslyUnknown = new List <StudentExpectedAttendanceEntry>(); List <StudentExpectedAttendanceEntry> needingUpdate = new List <StudentExpectedAttendanceEntry>(); List <StudentExpectedAttendanceEntry> noLongerExistsInExternalSystem = new List <StudentExpectedAttendanceEntry>(); int doneCount = 0; int totalExternalObjects = externalObjects.Count(); decimal donePercent = 0; decimal doneThresholdPercent = (decimal)0.1; decimal doneThresholdIncrease = (decimal)0.1; foreach (StudentExpectedAttendanceEntry externalObject in externalObjects) { // Check to see if we know about this object already StudentExpectedAttendanceEntry internalObject = internalRepository.Get(externalObject.iStudentID, externalObject.iSchoolYearID, externalObject.Date.Year, externalObject.Date.Month, externalObject.Date.Day); if (internalObject == null) { previouslyUnknown.Add(externalObject); } // Check to see if this object requires an update if (internalObject != null) { UpdateCheck check = internalObject.CheckIfUpdatesAreRequired(externalObject); if ((check == UpdateCheck.UpdatesRequired) || (config.ForceUpdate)) { needingUpdate.Add(externalObject); } } doneCount++; donePercent = (decimal)((decimal)doneCount / (decimal)totalExternalObjects); if (donePercent > doneThresholdPercent) { doneThresholdPercent = doneThresholdPercent + doneThresholdIncrease; Log((int)(donePercent * 100) + "% finished inspecting objects"); } if (doneCount == totalExternalObjects) { Log("100% finished inspecting objects"); } } Log("Found " + previouslyUnknown.Count() + " previously unknown"); Log("Found " + needingUpdate.Count() + " with updates"); // Commit these changes to the database if (previouslyUnknown.Count > 0) { if (config.AllowAdds) { Log(" > Adding " + previouslyUnknown.Count() + " new objects"); internalRepository.Add(previouslyUnknown); } else { Log(" > Not allowed to add, skipping " + previouslyUnknown.Count() + " adds"); } } if (needingUpdate.Count > 0) { if (config.AllowUpdates) { Log(" > Updating " + needingUpdate.Count() + " objects"); internalRepository.Update(needingUpdate); } else { Log(" > Not allowed to do updates, skipping " + needingUpdate.Count() + " updates"); } } Log("Finished syncing Expected Attendance"); }