/// <summary> /// Hangfire job to do the Annual Rollover tasks. /// </summary> /// <param name="context"></param> /// <param name="connectionstring"></param> public static void AnnualRolloverJob(PerformContext context, string connectionstring) { // open a connection to the database. DbContextOptionsBuilder <DbAppContext> options = new DbContextOptionsBuilder <DbAppContext>(); options.UseNpgsql(connectionstring); DbAppContext dbContext = new DbAppContext(null, options.Options); var progress = context.WriteProgressBar(); context.WriteLine("Starting Annual Rollover Job"); progress.SetValue(0); var equipmentTypes = dbContext.EquipmentTypes.ToList(); // The annual rollover will process all local areas in turn. var localareas = dbContext.LocalAreas.ToList(); // since this action is meant to run at the end of March, YTD calcs will always start from the year prior. int startingYear = DateTime.UtcNow.Year - 1; foreach (var localarea in localareas.WithProgress(progress)) { if (localarea.Name != null) { context.WriteLine("Local Area: " + localarea.Name); } else { context.WriteLine("Local Area ID: " + localarea.Id); } foreach (EquipmentType equipmentType in equipmentTypes) { using (DbAppContext etContext = new DbAppContext(null, options.Options)) { var data = etContext.Equipments .Include(x => x.LocalArea) .Include(x => x.DistrictEquipmentType.EquipmentType) .Where(x => x.Status == Equipment.STATUS_APPROVED && x.LocalArea.Id == localarea.Id && x.DistrictEquipmentType.EquipmentType.Id == equipmentType.Id) .Select(x => x) .ToList(); foreach (Equipment equipment in data) { // rollover the year equipment.ServiceHoursThreeYearsAgo = equipment.ServiceHoursTwoYearsAgo; equipment.ServiceHoursTwoYearsAgo = equipment.ServiceHoursLastYear; equipment.ServiceHoursLastYear = equipment.GetYTDServiceHours(dbContext, startingYear); equipment.CalculateYearsOfService(DateTime.UtcNow.Year); // blank out the override reason equipment.SeniorityOverrideReason = ""; // update the seniority score equipment.CalculateSeniority(); etContext.Equipments.Update(equipment); etContext.SaveChanges(); etContext.Entry(equipment).State = EntityState.Detached; } } // now update the rotation list using (DbAppContext abContext = new DbAppContext(null, options.Options)) { AssignBlocks(abContext, localarea.Id, equipmentType); } } } }
/// <summary> /// Update the local area rotation list /// </summary> /// <param name="context"></param> /// <param name="rentalRequestRotationListId"></param> public static void UpdateLocalAreaRotationList(this DbAppContext context, int rentalRequestRotationListId) { // start by getting the context. RentalRequestRotationList rentalRequestRotationList = context.RentalRequestRotationLists .Include(x => x.Equipment.LocalArea) .Include(x => x.Equipment.DistrictEquipmentType.EquipmentType) .FirstOrDefault(x => x.Id == rentalRequestRotationListId); if (rentalRequestRotationList != null && rentalRequestRotationList.Equipment != null && rentalRequestRotationList.Equipment.LocalArea != null && rentalRequestRotationList.Equipment.DistrictEquipmentType != null) { LocalAreaRotationList localAreaRotationList = context.LocalAreaRotationLists .Include(x => x.AskNextBlock1) .Include(x => x.AskNextBlock2) .Include(x => x.AskNextBlockOpen) .FirstOrDefault(x => x.LocalArea.Id == rentalRequestRotationList.Equipment.LocalArea.Id && x.DistrictEquipmentType.Id == rentalRequestRotationList.Equipment.DistrictEquipmentType.Id); if (localAreaRotationList == null || rentalRequestRotationList.Equipment.BlockNumber == null) { return; } switch (rentalRequestRotationList.Equipment.BlockNumber) { // primary block case 1: if (localAreaRotationList.AskNextBlock1.Id == rentalRequestRotationList.Equipment.Id) { localAreaRotationList.AskNextBlock1 = context.GetNextEquipmentOnLocalRotationList(rentalRequestRotationList.Equipment.LocalArea.Id, rentalRequestRotationList.Equipment.DistrictEquipmentType.EquipmentType.Id, rentalRequestRotationList.Equipment.Id, 1); } break; // secondary block for dump trucks, or open block for other types case 2: if (rentalRequestRotationList.Equipment.DistrictEquipmentType.EquipmentType.IsDumpTruck) { if (localAreaRotationList.AskNextBlock2.Id == rentalRequestRotationList.Equipment.Id) { localAreaRotationList.AskNextBlock1 = context.GetNextEquipmentOnLocalRotationList(rentalRequestRotationList.Equipment.LocalArea.Id, rentalRequestRotationList.Equipment.DistrictEquipmentType.EquipmentType.Id, rentalRequestRotationList.Equipment.Id, 2); } } else { if (localAreaRotationList.AskNextBlockOpen.Id == rentalRequestRotationList.Equipment.Id) { localAreaRotationList.AskNextBlockOpen = context.GetNextEquipmentOnLocalRotationList(rentalRequestRotationList.Equipment.LocalArea.Id, rentalRequestRotationList.Equipment.DistrictEquipmentType.EquipmentType.Id, rentalRequestRotationList.Equipment.Id, 2); } } break; // open block for dump trucks case 3: if (localAreaRotationList.AskNextBlockOpen.Id == rentalRequestRotationList.Equipment.Id) { localAreaRotationList.AskNextBlockOpen = context.GetNextEquipmentOnLocalRotationList(rentalRequestRotationList.Equipment.LocalArea.Id, rentalRequestRotationList.Equipment.DistrictEquipmentType.EquipmentType.Id, rentalRequestRotationList.Equipment.Id, 3); } break; } // update the local area rotation record context.LocalAreaRotationLists.Update(localAreaRotationList); context.SaveChanges(); } }
/// <summary> /// Assign blocks for an equipment list /// </summary> /// <param name="context"></param> /// <param name="localAreaId"></param> /// <param name="equipmentType"></param> public static void AssignBlocksDumpTruck(DbAppContext context, int localAreaId, int equipmentType) { // second pass will set the block int primaryCount = 0; int secondaryCount = 0; int openCount = 0; var data = context.Equipments .Include(x => x.Owner) .Include(x => x.DistrictEquipmentType.EquipmentType) .Where(x => x.Status == Equipment.STATUS_APPROVED && x.LocalArea.Id == localAreaId && x.DistrictEquipmentType.Id == equipmentType) .OrderByDescending(x => x.Seniority) .Select(x => x) .ToList(); List <int> primaryBlockOwners = new List <int>(); List <int> secondaryBlockOwners = new List <int>(); foreach (Equipment equipment in data) { // The primary block has a restriction such that each owner can only appear in the primary block once bool primaryFound = equipment.Owner != null && primaryBlockOwners.Contains(equipment.Owner.Id); if (primaryFound || primaryCount >= 10) // has to go in secondary block { // scan the secondary block. bool secondaryFound = equipment.Owner != null && secondaryBlockOwners.Contains(equipment.Owner.Id); if (secondaryFound || secondaryCount >= 10) // has to go in the Open block { equipment.BlockNumber = DistrictEquipmentType.OPEN_BLOCK_DUMP_TRUCK; openCount++; equipment.NumberInBlock = openCount; } else // add to the secondary block { if (equipment.Owner != null) { secondaryBlockOwners.Add(equipment.Owner.Id); } equipment.BlockNumber = DistrictEquipmentType.SECONDARY_BLOCK; secondaryCount++; equipment.NumberInBlock = secondaryCount; } } else // can go in primary block { if (equipment.Owner != null) { primaryBlockOwners.Add(equipment.Owner.Id); } equipment.BlockNumber = DistrictEquipmentType.PRIMARY_BLOCK; primaryCount++; equipment.NumberInBlock = primaryCount; } context.Equipments.Update(equipment); context.SaveChanges(); } }
/// <summary> /// Hangfire job to do the Annual Rollover tasks /// </summary> /// <param name="context"></param> /// <param name="connectionstring"></param> /// <param name="configuration"></param> public static void AnnualRolloverJob(PerformContext context, string connectionstring, IConfiguration configuration) { try { // open a connection to the database DbContextOptionsBuilder <DbAppContext> options = new DbContextOptionsBuilder <DbAppContext>(); options.UseNpgsql(connectionstring); DbAppContext dbContext = new DbAppContext(null, options.Options); // get processing rules SeniorityScoringRules scoringRules = new SeniorityScoringRules(configuration); // update progress bar IProgressBar progress = context.WriteProgressBar(); context.WriteLine("Starting Annual Rollover Job"); progress.SetValue(0); // get all equipment types List <EquipmentType> equipmentTypes = dbContext.EquipmentTypes.ToList(); // The annual rollover will process all local areas in turn List <LocalArea> localAreas = dbContext.LocalAreas.ToList(); // since this action is meant to run at the end of March, YTD calcs will always start from the year prior. int startingYear = DateTime.UtcNow.Year - 1; foreach (LocalArea localArea in localAreas.WithProgress(progress)) { if (localArea.Name != null) { context.WriteLine("Local Area: " + localArea.Name); } else { context.WriteLine("Local Area ID: " + localArea.Id); } foreach (EquipmentType equipmentType in equipmentTypes) { // it this a dumptruck? bool isDumpTruck = equipmentType.IsDumpTruck; // get rules for scoring and seniority block int seniorityScoring = isDumpTruck ? scoringRules.GetEquipmentScore("DumpTruck") : scoringRules.GetEquipmentScore(); int blockSize = isDumpTruck ? scoringRules.GetBlockSize("DumpTruck") : scoringRules.GetBlockSize(); int totalBlocks = isDumpTruck ? scoringRules.GetTotalBlocks("DumpTruck") : scoringRules.GetTotalBlocks(); using (DbAppContext etContext = new DbAppContext(null, options.Options)) { List <Equipment> data = etContext.Equipments .Include(x => x.LocalArea) .Include(x => x.DistrictEquipmentType.EquipmentType) .Where(x => x.Status == Equipment.StatusApproved && x.LocalArea.Id == localArea.Id && x.DistrictEquipmentType.EquipmentType.Id == equipmentType.Id) .Select(x => x) .ToList(); foreach (Equipment equipment in data) { // rollover the year equipment.ServiceHoursThreeYearsAgo = equipment.ServiceHoursTwoYearsAgo; equipment.ServiceHoursTwoYearsAgo = equipment.ServiceHoursLastYear; equipment.ServiceHoursLastYear = equipment.GetYTDServiceHours(dbContext, startingYear); equipment.CalculateYearsOfService(DateTime.UtcNow.Year); // blank out the override reason equipment.SeniorityOverrideReason = ""; // update the seniority score equipment.CalculateSeniority(seniorityScoring); etContext.Equipments.Update(equipment); etContext.SaveChanges(); etContext.Entry(equipment).State = EntityState.Detached; } } // now update the rotation list using (DbAppContext abContext = new DbAppContext(null, options.Options)) { int localAreaId = localArea.Id; int equipmentTypeId = equipmentType.Id; AssignBlocks(abContext, localAreaId, equipmentTypeId, blockSize, totalBlocks); } } } } catch (Exception e) { Console.WriteLine(e); throw; } }
private static bool AddedToBlock(DbAppContext context, int currentBlock, int totalBlocks, int blockSize, List <int>[] blocks, Equipment equipment) { try { // check if this record's Owner is null if (equipment.Owner == null) { return(false); // not adding this record to the block } if (blocks[currentBlock] == null) { blocks[currentBlock] = new List <int>(); } // check if the current block is full if (currentBlock < totalBlocks - 1 && blocks[currentBlock].Count >= blockSize) { return(false); // not adding this record to the block } // check if this record's Owner already exists in the block if (currentBlock < totalBlocks - 1 && blocks[currentBlock].Contains(equipment.Owner.Id)) { // add record to the next block if (blocks[currentBlock + 1] == null) { blocks[currentBlock + 1] = new List <int>(); } blocks[currentBlock + 1].Add(equipment.Owner.Id); // update the equipment record equipment.BlockNumber = currentBlock + 2; equipment.NumberInBlock = blocks[currentBlock + 1].Count; context.Equipments.Update(equipment); context.SaveChanges(); return(true); } // add record to the block blocks[currentBlock].Add(equipment.Owner.Id); // update the equipment record equipment.BlockNumber = currentBlock + 1; equipment.NumberInBlock = blocks[currentBlock].Count; context.Equipments.Update(equipment); context.SaveChanges(); // record added to the block return(true); } catch (Exception e) { Console.WriteLine("ERROR: AddedToBlock"); Console.WriteLine(e); throw; } }
/// <summary> /// Calculate the Seniority List /// </summary> /// <param name="context"></param> /// <param name="localAreaId"></param> /// <param name="districtEquipmentTypeId"></param> /// <param name="equipmentTypeId"></param> /// <param name="configuration"></param> public static void CalculateSeniorityList(this DbAppContext context, int localAreaId, int districtEquipmentTypeId, int equipmentTypeId, IConfiguration configuration) { try { Debug.WriteLine("CalculateSeniorityList [LocalAreaId: " + localAreaId + " | EquipmentType: " + districtEquipmentTypeId + "]"); // validate data if (context != null && context.LocalAreas.Any(x => x.Id == localAreaId) && context.DistrictEquipmentTypes.Any(x => x.Id == districtEquipmentTypeId)) { // get processing rules SeniorityScoringRules scoringRules = new SeniorityScoringRules(configuration); // get the associated equipment type EquipmentType equipmentTypeRecord = context.EquipmentTypes.FirstOrDefault(x => x.Id == equipmentTypeId); if (equipmentTypeRecord != null) { // get rules int seniorityScoring = equipmentTypeRecord.IsDumpTruck ? scoringRules.GetEquipmentScore("DumpTruck") : scoringRules.GetEquipmentScore(); int blockSize = equipmentTypeRecord.IsDumpTruck ? scoringRules.GetBlockSize("DumpTruck") : scoringRules.GetBlockSize(); int totalBlocks = equipmentTypeRecord.IsDumpTruck ? scoringRules.GetTotalBlocks("DumpTruck") : scoringRules.GetTotalBlocks(); // get all equipment records IQueryable <Equipment> data = context.Equipments .Where(x => x.LocalAreaId == localAreaId && x.DistrictEquipmentTypeId == districtEquipmentTypeId) .Select(x => x); // update the seniority score foreach (Equipment equipment in data) { if (equipment.Status != Equipment.StatusApproved) { equipment.SeniorityEffectiveDate = DateTime.Now; equipment.BlockNumber = null; equipment.ServiceHoursLastYear = null; equipment.ServiceHoursLastYear = null; equipment.ServiceHoursTwoYearsAgo = null; equipment.ServiceHoursThreeYearsAgo = null; equipment.Seniority = null; if (equipment.Status == Equipment.StatusArchived) { equipment.ArchiveCode = "Y"; } } else { equipment.CalculateSeniority(seniorityScoring); equipment.SeniorityEffectiveDate = DateTime.Now; equipment.ArchiveCode = "N"; } context.Equipments.Update(equipment); } context.SaveChanges(); // put equipment into the correct blocks AssignBlocks(context, localAreaId, districtEquipmentTypeId, blockSize, totalBlocks); } } } catch (Exception e) { Console.WriteLine("ERROR: CalculateSeniorityList"); Console.WriteLine(e); throw; } }