示例#1
0
        private static HetRentalRequest DropHiredEquipment(HetRentalRequest rentalRequest, DbAppContext context)
        {
            // check if any items have "Active" contracts - and drop them from the list
            // * ensure we ignore "blank" rental agreements (i.e. rental request is null)

            int?statusIdRentalAgreement = StatusHelper.GetStatusId(HetRentalAgreement.StatusActive, "rentalAgreementStatus", context);

            if (statusIdRentalAgreement == null)
            {
                throw new ArgumentException("Status Id cannot be null");
            }

            int listSize = rentalRequest.HetRentalRequestRotationList.Count;

            for (int i = listSize - 1; i >= 0; i--)
            {
                bool agreementExists = context.HetRentalAgreement.AsNoTracking()
                                       .Any(x => x.EquipmentId == rentalRequest.HetRentalRequestRotationList.ElementAt(i).EquipmentId&&
                                            x.RentalRequestId != null &&
                                            x.RentalAgreementStatusTypeId == statusIdRentalAgreement);

                if (agreementExists)
                {
                    rentalRequest.HetRentalRequestRotationList.Remove(rentalRequest.HetRentalRequestRotationList.ElementAt(i));
                }
            }

            return(rentalRequest);
        }
示例#2
0
        /// <summary>
        /// Returns true if any equipment associated with this owner is on an active rotation list
        /// </summary>
        /// <param name="id"></param>
        /// <param name="context"></param>
        /// <returns></returns>
        public static bool RentalRequestStatus(int id, DbAppContext context)
        {
            // get equipment status types
            int?statusIdActive = StatusHelper.GetStatusId(HetEquipment.StatusApproved, "equipmentStatus", context);

            if (statusIdActive == null)
            {
                throw new ArgumentException("Status Code not found");
            }

            // get rental request status type
            int?statusIdInProgress = StatusHelper.GetStatusId(HetRentalRequest.StatusInProgress, "rentalRequestStatus", context);

            if (statusIdInProgress == null)
            {
                throw new ArgumentException("Status Code not found");
            }

            return(context.HetRentalRequestRotationList.AsNoTracking()
                   .Include(x => x.RentalRequest)
                   .Include(x => x.Equipment)
                   .Any(x => x.Equipment.OwnerId == id &&
                        x.Equipment.EquipmentStatusTypeId == statusIdActive &&
                        x.RentalRequest.RentalRequestStatusTypeId == statusIdInProgress));
        }
示例#3
0
        /// <summary>
        /// Set the Status of the Rental Request Rotation List
        /// </summary>
        /// <param name="rentalRequest"></param>
        /// <param name="context"></param>
        public static string RentalRequestStatus(HetRentalRequest rentalRequest, DbAppContext context)
        {
            string tempStatus = "New";

            // validate input parameters
            if (rentalRequest?.LocalAreaId != null && rentalRequest.DistrictEquipmentTypeId != null)
            {
                int?statusIdInProgress = StatusHelper.GetStatusId(HetRentalRequest.StatusInProgress, "rentalRequestStatus", context);
                if (statusIdInProgress == null)
                {
                    return(null);
                }

                // check if there is an existing "In Progress" Rental Request
                List <HetRentalRequest> requests = context.HetRentalRequest
                                                   .Where(x => x.DistrictEquipmentType.DistrictEquipmentTypeId == rentalRequest.DistrictEquipmentTypeId &&
                                                          x.LocalArea.LocalAreaId == rentalRequest.LocalAreaId &&
                                                          x.RentalRequestStatusTypeId == statusIdInProgress)
                                                   .ToList();

                tempStatus = requests.Count == 0 ? "In Progress" : "New";
            }

            return(tempStatus);
        }
示例#4
0
        /// <summary>
        /// Get an Owner record
        /// </summary>
        /// <param name="id"></param>
        /// <param name="context"></param>
        /// <param name="configuration"></param>
        /// <returns></returns>
        public static HetOwner GetRecord(int id, DbAppContext context, IConfiguration configuration)
        {
            // get equipment status types
            int?statusIdArchived = StatusHelper.GetStatusId(HetEquipment.StatusArchived, "equipmentStatus", context);

            if (statusIdArchived == null)
            {
                throw new ArgumentException("Status Code not found");
            }

            // get owner record
            HetOwner owner = context.HetOwner.AsNoTracking()
                             .Include(x => x.OwnerStatusType)
                             .Include(x => x.LocalArea.ServiceArea.District.Region)
                             .Include(x => x.HetEquipment)
                             .ThenInclude(y => y.LocalArea.ServiceArea.District.Region)
                             .Include(x => x.HetEquipment)
                             .ThenInclude(y => y.DistrictEquipmentType)
                             .ThenInclude(z => z.EquipmentType)
                             .Include(x => x.HetEquipment)
                             .ThenInclude(y => y.Owner)
                             .ThenInclude(c => c.PrimaryContact)
                             .Include(x => x.HetEquipment)
                             .ThenInclude(y => y.EquipmentStatusType)
                             .Include(x => x.HetEquipment)
                             .ThenInclude(y => y.HetEquipmentAttachment)
                             .Include(x => x.HetContact)
                             .Include(x => x.PrimaryContact)
                             .FirstOrDefault(a => a.OwnerId == id);

            if (owner != null)
            {
                // remove any archived equipment
                owner.HetEquipment = owner.HetEquipment.Where(e => e.EquipmentStatusTypeId != statusIdArchived).ToList();

                // populate the "Status" description
                owner.Status = owner.OwnerStatusType.OwnerStatusTypeCode;

                foreach (HetEquipment equipment in owner.HetEquipment)
                {
                    equipment.IsHired         = EquipmentHelper.IsHired(id, context);
                    equipment.NumberOfBlocks  = EquipmentHelper.GetNumberOfBlocks(equipment, configuration);
                    equipment.HoursYtd        = EquipmentHelper.GetYtdServiceHours(id, context);
                    equipment.Status          = equipment.EquipmentStatusType.EquipmentStatusTypeCode;
                    equipment.EquipmentNumber = int.Parse(Regex.Match(equipment.EquipmentCode, @"\d+").Value);
                }

                // HETS-1115 - Do not allow changing seniority affecting entities if an active request exists
                owner.ActiveRentalRequest = RentalRequestStatus(id, context);
            }

            return(owner);
        }
示例#5
0
        private static bool IsEquipmentHired(int?equipmentId, DbAppContext context)
        {
            if (equipmentId == null)
            {
                return(false);
            }

            // check if this item has an "Active" contract
            int?statusIdRentalAgreement = StatusHelper.GetStatusId(HetRentalAgreement.StatusActive, "rentalAgreementStatus", context);

            if (statusIdRentalAgreement == null)
            {
                throw new ArgumentException("Status Id cannot be null");
            }

            bool agreementExists = context.HetRentalAgreement.AsNoTracking()
                                   .Any(x => x.EquipmentId == equipmentId &&
                                        x.RentalRequestId != null &&
                                        x.RentalAgreementStatusTypeId == statusIdRentalAgreement);

            return(agreementExists);
        }
示例#6
0
        public static void MergeDistrictEquipmentTypes(PerformContext context, string seniorityScoringRules,
                                                       string connectionString)
        {
            // open a connection to the database
            DbAppContext dbContext = new DbAppContext(connectionString);

            // get equipment status
            int?equipmentStatusId = StatusHelper.GetStatusId(HetEquipment.StatusApproved, "equipmentStatus", dbContext);

            if (equipmentStatusId == null)
            {
                throw new ArgumentException("Status Code not found");
            }

            // **************************************************
            // Phase 1: Identify Master District Equipment Types
            // **************************************************
            context.WriteLine("Phase 1: Identify Master District Equipment Types");
            IProgressBar progress = context.WriteProgressBar();

            progress.SetValue(0);

            // get records
            List <MergeRecord> masterList = dbContext.HetDistrictEquipmentType.AsNoTracking()
                                            .Where(x => x.ServiceAreaId != null &&
                                                   x.Deleted == false)
                                            .Select(x => new MergeRecord
            {
                DistrictEquipmentTypeId = x.DistrictEquipmentTypeId,
                DistrictEquipmentName   = x.DistrictEquipmentName,
                EquipmentPrefix         = GetPrefix(x.DistrictEquipmentName),
                DistrictId      = x.DistrictId,
                EquipmentTypeId = x.EquipmentTypeId
            })
                                            .Distinct()
                                            .ToList();

            // sort the list accordingly
            masterList = masterList
                         .OrderBy(x => x.DistrictId)
                         .ThenBy(x => x.EquipmentTypeId)
                         .ThenBy(x => x.EquipmentPrefix).ToList();

            int    increment       = 0;
            int?   currentDistrict = -1;
            int?   masterDistrictEquipmentTypeId = -1;
            int?   currentEquipmentType          = -1;
            string currentPrefix = "";

            foreach (MergeRecord detRecord in masterList)
            {
                bool newMerge;

                if (detRecord.DistrictId != currentDistrict ||
                    detRecord.EquipmentTypeId != currentEquipmentType ||
                    detRecord.EquipmentPrefix != currentPrefix)
                {
                    newMerge             = true;
                    currentDistrict      = detRecord.DistrictId;
                    currentEquipmentType = detRecord.EquipmentTypeId;
                    currentPrefix        = detRecord.EquipmentPrefix;

                    masterDistrictEquipmentTypeId = detRecord.DistrictEquipmentTypeId;
                    detRecord.Master = true;
                    detRecord.MasterDistrictEquipmentTypeId = masterDistrictEquipmentTypeId;
                }
                else
                {
                    newMerge         = false;
                    detRecord.Master = false;
                    detRecord.MasterDistrictEquipmentTypeId = masterDistrictEquipmentTypeId;
                }

                // kickoff the merge for this district, equipment type and prefix
                if (newMerge)
                {
                    int    district   = currentDistrict ?? -1;
                    int    type       = currentEquipmentType ?? -1;
                    string prefix     = currentPrefix;
                    string masterName = "";

                    List <MergeRecord> types = masterList
                                               .Where(x => x.DistrictId == district &&
                                                      x.EquipmentTypeId == type &&
                                                      x.EquipmentPrefix == prefix).ToList();

                    // create master name and update master record
                    foreach (MergeRecord equipmentType in types)
                    {
                        string temp  = equipmentType.DistrictEquipmentName.Replace(currentPrefix, "").Trim();
                        int    start = temp.IndexOf("-", StringComparison.Ordinal);
                        if (start > -1)
                        {
                            start++;
                        }
                        int length = temp.Length - start < 0 ? 0 : temp.Length - start;
                        temp = temp.Substring(start, length).Trim();

                        masterName = masterName.Length > 0 ?
                                     $"{masterName} | {temp}" :
                                     temp;
                    }

                    masterName = $"{currentPrefix} - {masterName}";
                    types.ElementAt(0).DistrictEquipmentName = masterName;
                }

                // update status bar
                increment++;
                progress.SetValue(Convert.ToInt32((decimal)(masterList.Count - (masterList.Count - increment)) / masterList.Count * 100));
            }

            // done!
            progress.SetValue(100);

            // **************************************************
            // Phase 2: Update Master District Equipment Types
            // **************************************************
            context.WriteLine("Phase 2: Update Master District Equipment Types");
            progress = context.WriteProgressBar();
            progress.SetValue(0);

            List <MergeRecord> masterRecords = masterList.Where(x => x.Master).ToList();

            increment = 0;

            foreach (MergeRecord detRecord in masterRecords)
            {
                // get det record & update name
                HetDistrictEquipmentType det = dbContext.HetDistrictEquipmentType
                                               .First(x => x.DistrictEquipmentTypeId == detRecord.DistrictEquipmentTypeId);

                det.DistrictEquipmentName = detRecord.DistrictEquipmentName;
                det.ServiceAreaId         = null;

                // save changes to district equipment types and associated equipment records
                dbContext.SaveChangesForImport();

                // update status bar
                increment++;
                progress.SetValue(Convert.ToInt32((decimal)(masterRecords.Count - (masterRecords.Count - increment)) / masterRecords.Count * 100));
            }

            // done!
            progress.SetValue(100);

            // **************************************************
            // Phase 3: Update Non-Master District Equipment Types
            // **************************************************
            context.WriteLine("Phase 3: Update Non-Master District Equipment Types");
            progress = context.WriteProgressBar();
            progress.SetValue(0);

            List <MergeRecord> mergeRecords = masterList.Where(x => !x.Master).ToList();

            increment = 0;

            foreach (MergeRecord detRecord in mergeRecords)
            {
                int originalDistrictEquipmentTypeId = detRecord.DistrictEquipmentTypeId;
                int?newDistrictEquipmentTypeId      = detRecord.MasterDistrictEquipmentTypeId;

                // get equipment & update
                IEnumerable <HetEquipment> equipmentRecords = dbContext.HetEquipment
                                                              .Where(x => x.DistrictEquipmentTypeId == originalDistrictEquipmentTypeId);

                foreach (HetEquipment equipment in equipmentRecords)
                {
                    equipment.DistrictEquipmentTypeId = newDistrictEquipmentTypeId;
                }

                // save changes to associated equipment records
                dbContext.SaveChangesForImport();

                // get det record
                HetDistrictEquipmentType det = dbContext.HetDistrictEquipmentType
                                               .First(x => x.DistrictEquipmentTypeId == originalDistrictEquipmentTypeId);

                // delete old det record
                HetRentalRequest request = dbContext.HetRentalRequest.AsNoTracking()
                                           .FirstOrDefault(x => x.DistrictEquipmentTypeId == originalDistrictEquipmentTypeId);

                HetLocalAreaRotationList rotationList = dbContext.HetLocalAreaRotationList.AsNoTracking()
                                                        .FirstOrDefault(x => x.DistrictEquipmentTypeId == originalDistrictEquipmentTypeId);

                if (request != null || rotationList != null)
                {
                    det.Deleted = true;
                }
                else
                {
                    dbContext.HetDistrictEquipmentType.Remove(det);
                }

                // save changes to district equipment types and associated equipment records
                dbContext.SaveChangesForImport();

                // update status bar
                increment++;
                progress.SetValue(Convert.ToInt32((decimal)(mergeRecords.Count - (mergeRecords.Count - increment)) / mergeRecords.Count * 100));
            }

            // done!
            progress.SetValue(100);

            // **************************************************
            // Phase 4: Update seniority and block assignments
            // **************************************************
            context.WriteLine("Phase 4: Update seniority and block assignments");
            progress = context.WriteProgressBar();
            progress.SetValue(0);

            increment = 0;

            foreach (MergeRecord detRecord in masterRecords)
            {
                // update the seniority and block assignments for the master record
                List <HetLocalArea> localAreas = dbContext.HetEquipment.AsNoTracking()
                                                 .Include(x => x.LocalArea)
                                                 .Where(x => x.EquipmentStatusTypeId == equipmentStatusId &&
                                                        x.DistrictEquipmentTypeId == detRecord.DistrictEquipmentTypeId)
                                                 .Select(x => x.LocalArea)
                                                 .Distinct()
                                                 .ToList();

                foreach (HetLocalArea localArea in localAreas)
                {
                    EquipmentHelper.RecalculateSeniority(localArea.LocalAreaId,
                                                         detRecord.DistrictEquipmentTypeId, dbContext, seniorityScoringRules);
                }

                // save changes to equipment records
                dbContext.SaveChangesForImport();

                // update status bar
                increment++;
                progress.SetValue(Convert.ToInt32((decimal)(masterRecords.Count - (masterRecords.Count - increment)) / masterRecords.Count * 100));
            }

            // done!
            progress.SetValue(100);

            // **************************************************
            // Phase 5: Cleanup "empty" District Equipment Types
            // **************************************************
            context.WriteLine("Phase 5: Cleanup empty District Equipment Types");
            progress = context.WriteProgressBar();
            progress.SetValue(0);

            // get records
            List <HetDistrictEquipmentType> districtEquipmentTypes = dbContext.HetDistrictEquipmentType.AsNoTracking()
                                                                     .Include(x => x.HetEquipment)
                                                                     .Where(x => x.Deleted == false)
                                                                     .Distinct()
                                                                     .ToList();

            increment = 0;

            foreach (HetDistrictEquipmentType districtEquipmentType in districtEquipmentTypes)
            {
                int districtEquipmentTypeId = districtEquipmentType.DistrictEquipmentTypeId;

                // does this det have any equipment records?
                if (districtEquipmentType.HetEquipment.Count < 1)
                {
                    // get det record
                    HetDistrictEquipmentType det = dbContext.HetDistrictEquipmentType
                                                   .First(x => x.DistrictEquipmentTypeId == districtEquipmentTypeId);

                    // delete old det record
                    HetRentalRequest request = dbContext.HetRentalRequest.AsNoTracking()
                                               .FirstOrDefault(x => x.DistrictEquipmentTypeId == districtEquipmentTypeId);

                    HetLocalAreaRotationList rotationList = dbContext.HetLocalAreaRotationList.AsNoTracking()
                                                            .FirstOrDefault(x => x.DistrictEquipmentTypeId == districtEquipmentTypeId);

                    if (request != null || rotationList != null)
                    {
                        det.Deleted = true;
                    }
                    else
                    {
                        dbContext.HetDistrictEquipmentType.Remove(det);
                    }

                    // save changes to district equipment types and associated equipment records
                    dbContext.SaveChangesForImport();
                }

                // update status bar
                increment++;
                progress.SetValue(Convert.ToInt32((decimal)(districtEquipmentTypes.Count - (districtEquipmentTypes.Count - increment)) / districtEquipmentTypes.Count * 100));
            }

            // done!
            progress.SetValue(100);
        }
        /// <summary>
        /// Calculate the Seniority List
        /// </summary>
        /// <param name="localAreaId"></param>
        /// <param name="districtEquipmentTypeId"></param>
        /// <param name="equipmentTypeId"></param>
        /// <param name="context"></param>
        /// <param name="configuration"></param>
        public static void CalculateSeniorityList(int localAreaId, int districtEquipmentTypeId,
                                                  int equipmentTypeId, DbAppContext context, IConfiguration configuration)
        {
            try
            {
                // validate data
                if (context != null &&
                    context.HetLocalArea.Any(x => x.LocalAreaId == localAreaId) &&
                    context.HetDistrictEquipmentType.Any(x => x.DistrictEquipmentTypeId == districtEquipmentTypeId))
                {
                    // get processing rules
                    SeniorityScoringRules scoringRules = new SeniorityScoringRules(configuration);

                    // get the associated equipment type
                    HetEquipmentType equipmentTypeRecord = context.HetEquipmentType
                                                           .FirstOrDefault(x => x.EquipmentTypeId == 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 <HetEquipment> data = context.HetEquipment
                                                         .Include(x => x.EquipmentStatusType)
                                                         .Where(x => x.LocalAreaId == localAreaId &&
                                                                x.DistrictEquipmentTypeId == districtEquipmentTypeId);

                        // get status id
                        int?eqStatusId =
                            StatusHelper.GetStatusId(HetEquipment.StatusApproved, "equipmentStatus", context);
                        if (eqStatusId == null)
                        {
                            throw new ArgumentException("Status Code not found");
                        }

                        // update the seniority score
                        foreach (HetEquipment equipment in data)
                        {
                            if (equipment.EquipmentStatusTypeId != eqStatusId)
                            {
                                equipment.SeniorityEffectiveDate = DateTime.UtcNow;
                                equipment.BlockNumber            = null;
                                equipment.Seniority     = null;
                                equipment.NumberInBlock = null;
                            }
                            else
                            {
                                equipment.CalculateSeniority(seniorityScoring);
                                equipment.SeniorityEffectiveDate = DateTime.UtcNow;
                            }

                            context.HetEquipment.Update(equipment);
                        }

                        context.SaveChanges();

                        // put equipment into the correct blocks
                        AssignBlocks(localAreaId, districtEquipmentTypeId, blockSize, totalBlocks, context);
                    }
                }
            }
            catch (Exception e)
            {
                Console.WriteLine("ERROR: CalculateSeniorityList");
                Console.WriteLine(e);
                throw;
            }
        }
示例#8
0
        /// <summary>
        /// Create Rental Request Rotation List
        /// </summary>
        /// <param name="request"></param>
        /// <param name="context"></param>
        /// <param name="configuration"></param>
        public static HetRentalRequest CreateRotationList(HetRentalRequest request, DbAppContext context, IConfiguration configuration)
        {
            request.HetRentalRequestRotationList = new List <HetRentalRequestRotationList>();

            // validate input parameters
            if (request.LocalAreaId == null || request.DistrictEquipmentTypeId == null)
            {
                return(request);
            }

            int currentSortOrder = 1;

            // get the number of blocks for this piece of equipment
            int numberOfBlocks = GetNumberOfBlocks(request, context, configuration);

            numberOfBlocks = numberOfBlocks + 1;

            int?statusId = StatusHelper.GetStatusId(HetEquipment.StatusApproved, "equipmentStatus", context);

            if (statusId == null)
            {
                throw new ArgumentException("Status Id cannot be null");
            }

            // get the equipment based on the current seniority list for the area
            // (and sort the results based on block then
            //      numberInBlock -> ensures consistency with the UI)
            for (int currentBlock = 1; currentBlock <= numberOfBlocks; currentBlock++)
            {
                // start by getting the current set of equipment for the given equipment type
                List <HetEquipment> blockEquipment = context.HetEquipment.AsNoTracking()
                                                     .Where(x => x.DistrictEquipmentTypeId == request.DistrictEquipmentTypeId &&
                                                            x.BlockNumber == currentBlock &&
                                                            x.LocalAreaId == request.LocalAreaId &&
                                                            x.EquipmentStatusTypeId == statusId)
                                                     .OrderBy(x => x.NumberInBlock)
                                                     .ToList();

                int listSize = blockEquipment.Count;

                // sets the rotation list sort order
                int currentPosition = 0;

                for (int i = 0; i < listSize; i++)
                {
                    HetRentalRequestRotationList rentalRequestRotationList = new HetRentalRequestRotationList
                    {
                        Equipment             = blockEquipment[i],
                        EquipmentId           = blockEquipment[i].EquipmentId,
                        SeniorityFloat        = blockEquipment[i].Seniority,
                        BlockNumber           = blockEquipment[i].BlockNumber,
                        AppCreateTimestamp    = DateTime.UtcNow,
                        RotationListSortOrder = currentSortOrder
                    };

                    request.HetRentalRequestRotationList.Add(rentalRequestRotationList);

                    currentPosition++;
                    currentSortOrder++;

                    if (currentPosition >= listSize)
                    {
                        currentPosition = 0;
                    }
                }
            }

            // update the local area rotation list - find record #1
            request = SetupNewRotationList(request, numberOfBlocks, context);

            // remove equipment records
            foreach (HetRentalRequestRotationList rotationList in request.HetRentalRequestRotationList)
            {
                rotationList.Equipment = null;
            }

            // Done!
            return(request);
        }
示例#9
0
        /// <summary>
        /// Annual Rollover
        /// </summary>
        /// <param name="context"></param>
        /// <param name="districtId"></param>
        /// <param name="seniorityScoringRules"></param>
        /// <param name="connectionString"></param>
        public static void AnnualRolloverJob(PerformContext context, int districtId, string seniorityScoringRules, string connectionString)
        {
            try
            {
                // open a connection to the database
                DbAppContext dbContext = new DbAppContext(connectionString);

                // get processing rules
                SeniorityScoringRules scoringRules = new SeniorityScoringRules(seniorityScoringRules);

                // update progress bar
                IProgressBar progress = context.WriteProgressBar();
                context.WriteLine("Starting Annual Rollover Job - District #" + districtId);

                progress.SetValue(0);

                // validate district id
                HetDistrict district = dbContext.HetDistrict.AsNoTracking()
                                       .FirstOrDefault(x => x.DistrictId == districtId);

                if (district == null)
                {
                    context.WriteLine("District not found");
                    progress.SetValue(100);
                    return;
                }

                // get status record - and ensure we're active
                HetDistrictStatus status = GetRecord(districtId, dbContext);

                if (status == null)
                {
                    context.WriteLine("District Status not found");
                    progress.SetValue(100);
                    return;
                }

                // get equipment status
                int?statusId = StatusHelper.GetStatusId(HetEquipment.StatusApproved, "equipmentStatus", dbContext);
                if (statusId == null)
                {
                    context.WriteLine("Equipment Status not found");
                    progress.SetValue(100);
                    return;
                }

                // determine the "Rollover Date" (required for testing)
                DateTime rolloverDate;

                if (DateTime.UtcNow.Month == 1 || DateTime.UtcNow.Month == 2 || DateTime.UtcNow.Month == 3)
                {
                    if (status.NextFiscalYear == null)
                    {
                        status.NextFiscalYear = DateTime.UtcNow.Year;
                    }

                    rolloverDate = new DateTime((int)status.NextFiscalYear, DateTime.UtcNow.Month, DateTime.UtcNow.Day);
                }
                else
                {
                    if (status.CurrentFiscalYear == null)
                    {
                        status.CurrentFiscalYear = DateTime.UtcNow.Year;
                    }

                    rolloverDate = new DateTime((int)status.CurrentFiscalYear, DateTime.UtcNow.Month, DateTime.UtcNow.Day);
                }

                // get all district equipment types
                List <HetDistrictEquipmentType> equipmentTypes = dbContext.HetDistrictEquipmentType.AsNoTracking()
                                                                 .Include(x => x.EquipmentType)
                                                                 .Where(x => x.DistrictId == districtId).ToList();

                // get all local areas
                List <HetLocalArea> localAreas = dbContext.HetLocalArea.AsNoTracking()
                                                 .Where(a => a.ServiceArea.DistrictId == districtId).ToList();

                // update status - job is kicked off
                int localAreaCompleteCount = 0;
                int equipmentCompleteCount = 0;

                UpdateStatusKickoff(dbContext, status, localAreaCompleteCount, equipmentCompleteCount);

                // process all local areas and equipment types
                foreach (HetLocalArea localArea in localAreas.WithProgress(progress))
                {
                    // re-open the connection
                    dbContext = new DbAppContext(connectionString);

                    if (localArea.Name != null)
                    {
                        context.WriteLine("Local Area: " + localArea.Name);
                    }
                    else
                    {
                        context.WriteLine("Local Area ID: " + localArea.LocalAreaId);
                    }

                    // reset equipment counter
                    equipmentCompleteCount = 0;

                    foreach (HetDistrictEquipmentType equipmentType in equipmentTypes)
                    {
                        // it this a dump truck?
                        bool isDumpTruck = equipmentType.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(connectionString))
                        {
                            List <HetEquipment> data = etContext.HetEquipment
                                                       .Include(x => x.LocalArea)
                                                       .Include(x => x.DistrictEquipmentType.EquipmentType)
                                                       .Where(x => x.EquipmentStatusTypeId == statusId &&
                                                              x.LocalAreaId == localArea.LocalAreaId &&
                                                              x.DistrictEquipmentTypeId == equipmentType.DistrictEquipmentTypeId)
                                                       .ToList();

                            foreach (HetEquipment equipment in data)
                            {
                                // rollover the year
                                equipment.ServiceHoursThreeYearsAgo = equipment.ServiceHoursTwoYearsAgo;
                                equipment.ServiceHoursTwoYearsAgo   = equipment.ServiceHoursLastYear;
                                equipment.ServiceHoursLastYear      = EquipmentHelper.GetYtdServiceHours(equipment.EquipmentId, dbContext, rolloverDate);
                                equipment.CalculateYearsOfService(DateTime.UtcNow);

                                // blank out the override reason
                                equipment.SeniorityOverrideReason = "";

                                // update the seniority score
                                equipment.CalculateSeniority(seniorityScoring);

                                etContext.HetEquipment.Update(equipment);
                                etContext.SaveChanges();
                            }
                        }

                        // now update the rotation list
                        using (DbAppContext abContext = new DbAppContext(connectionString))
                        {
                            int localAreaId     = localArea.LocalAreaId;
                            int equipmentTypeId = equipmentType.DistrictEquipmentTypeId;

                            SeniorityListHelper.AssignBlocks(localAreaId, equipmentTypeId, blockSize, totalBlocks, abContext);
                        }

                        // increment counters and update status
                        equipmentCompleteCount++;
                        UpdateStatus(dbContext, status, localAreaCompleteCount, equipmentCompleteCount);
                    }

                    // increment counters and update status
                    localAreaCompleteCount++;
                    UpdateStatus(dbContext, status, localAreaCompleteCount, equipmentCompleteCount);
                    if (status.ProgressPercentage != null)
                    {
                        progress.SetValue((int)status.ProgressPercentage);
                    }
                }

                // done!
                UpdateStatusComplete(dbContext, status, localAreaCompleteCount, equipmentCompleteCount);
                progress.SetValue(100);

                // **********************************************************
                // regenerate Owner Secret Keys for this district
                // **********************************************************
                dbContext = new DbAppContext(connectionString);

                context.WriteLine("");
                context.WriteLine("Generate New Secret Keys - District #" + districtId);
                progress = context.WriteProgressBar();

                progress.SetValue(0);
                // get records
                List <HetOwner> owners = dbContext.HetOwner.AsNoTracking()
                                         .Where(x => x.BusinessId == null &&
                                                x.LocalArea.ServiceArea.DistrictId == districtId)
                                         .ToList();

                int i          = 0;
                int ownerCount = owners.Count;

                foreach (HetOwner owner in owners)
                {
                    i++;
                    string key = SecretKeyHelper.RandomString(8, owner.OwnerId);

                    string temp = owner.OwnerCode;

                    if (string.IsNullOrEmpty(temp))
                    {
                        temp = SecretKeyHelper.RandomString(4, owner.OwnerId);
                    }

                    key = temp + "-" + (rolloverDate.Year + 1) + "-" + key;

                    // get owner and update
                    HetOwner ownerRecord = dbContext.HetOwner.First(x => x.OwnerId == owner.OwnerId);
                    ownerRecord.SharedKey = key;
                    dbContext.HetOwner.Update(ownerRecord);

                    decimal tempProgress = Convert.ToDecimal(i) / Convert.ToDecimal(ownerCount);
                    tempProgress = tempProgress * 100;
                    int percentComplete = Convert.ToInt32(tempProgress);

                    if (percentComplete < 1)
                    {
                        percentComplete = 1;
                    }
                    if (percentComplete > 99)
                    {
                        percentComplete = 100;
                    }

                    progress.SetValue(percentComplete);
                }

                // save remaining updates - done!
                dbContext.SaveChangesForImport();
                progress.SetValue(100);
                context.WriteLine("Generate New Secret Keys - Done");
            }
            catch (Exception e)
            {
                Console.WriteLine(e);
                throw;
            }
        }