///<summary>Calculates the info for the dashboard</summary>
		private void RefreshAll() {
			//Validation
			if(_jobSprintCur.DateStart>_jobSprintCur.DateEndTarget) {
				return;
			}
			#region Variables
			_listJobSprintLinks=JobSprintLinks.GetForSprint(_jobSprintCur.JobSprintNum);
			_listAttachedJobs=_listJobsAll.FindAll(x => _listJobSprintLinks.Select(y => y.JobNum).Contains(x.JobNum)
				&& x.Category.In(JobCategory.Feature,JobCategory.Enhancement,JobCategory.InternalRequest,JobCategory.HqRequest,JobCategory.ProgramBridge));
			List<Job> listBugJobs=_listJobsAll.FindAll(x => x.Category==JobCategory.Bug);
			DateTime dateStart=_jobSprintCur.DateStart;
			DateTime dateProgress=DateTime.Today.Date;
			DateTime dateEnd=_jobSprintCur.DateEndTarget;
			List<Job> listCompletedBugJobs=listBugJobs.FindAll(x => x.PhaseCur.In(JobPhase.Documentation,JobPhase.Complete)
				&& x.ListJobLinks.Count(y => y.LinkType==JobLinkType.Bug)>0
				&& DateTimeOD.Between(x.ListJobLogs.FirstOrDefault(y => y.Description.Contains("Job implemented"))?.DateTimeEntry??DateTime.MinValue,dateStart,dateEnd));
			List<Job> listRemainingBugJobs=listBugJobs.FindAll(x => x.PhaseCur.In(JobPhase.Concept,JobPhase.Definition,JobPhase.Quote,JobPhase.Development)
				&& x.ListJobLinks.Count(y => y.LinkType==JobLinkType.Bug)>0);
			double totalDays=(dateEnd - dateStart).TotalDays;
			double totalDaysElapsed=(dateProgress - dateStart).TotalDays;
			double totalDaysLeft=totalDays-totalDaysElapsed;
			int targetValuePercent=(int)(totalDaysElapsed/totalDays*100);
			double jobPercent=_jobSprintCur.JobPercent;
			double avgDevHours=_jobSprintCur.HoursAverageDevelopment;
			double avgBreakHours=_jobSprintCur.HoursAverageBreak;
			double totalAllocatedHours=0;
			double totalCompletedHours=0;
			double hoursComplete=_listAttachedJobs.Sum(x => x.HoursActual);
			double hoursTotal=_listAttachedJobs.Sum(x => x.HoursEstimate);
			double hoursRemaining=hoursTotal-hoursComplete>0?hoursTotal-hoursComplete:0;
			double totalJobsRemaining=_listAttachedJobs.Where(x => x.PhaseCur.In(JobPhase.Concept,JobPhase.Definition,JobPhase.Quote,JobPhase.Development)).Count()+listRemainingBugJobs.Count;
			double totalJobsCompleted=_listAttachedJobs.Where(x => x.PhaseCur.In(JobPhase.Documentation,JobPhase.Complete)).Count()+listCompletedBugJobs.Count();
			#endregion
			#region Top Panel
			this.Text=_jobSprintCur.Title;
			textStartDate.Text=_jobSprintCur.DateStart.ToShortDateString();
			textEndDate.Text=_jobSprintCur.DateEndTarget.ToShortDateString();
			//Calculate hours for the list of jobs attached to the sprint
			foreach(Job job in _listAttachedJobs) {
				//Do not include "completed" jobs
				if(job.PhaseCur.In(JobPhase.Documentation,JobPhase.Complete,JobPhase.Cancelled)) {
					continue;
				}
				double estimate=job.HoursEstimate;
				if(job.HoursEstimateDevelopment==0) {
					estimate+=avgDevHours;
				}
				totalAllocatedHours+=estimate;
				totalAllocatedHours-=job.HoursActual;
				totalCompletedHours+=job.HoursActual;
			}
			//Calculate and Set Work Complete Percent
			double completionPercentage=0;
			completionPercentage=(totalCompletedHours/totalAllocatedHours)*100;
			if(Double.IsNaN(completionPercentage)) {
				completionPercentage=0;
			}
			completionPercentage=completionPercentage>=100?100:completionPercentage;
			//Set Progress Bar Value and TargetValue
			textCompletePercentage.Text=(int)completionPercentage+"%";
			progressComplete.Value=(int)completionPercentage;
			progressComplete.TargetValue=(int)completionPercentage;
			textElapsedPercentage.Text=targetValuePercent+"%";
			progressElapsed.Value=targetValuePercent;
			progressElapsed.TargetValue=targetValuePercent;
			//Set Days Left
			textDaysLeft.Text=totalDaysLeft+" Days Left";
			//textScopeChange.Text=(_listAttachedJobs.Where(x => x.ListJobLogs.Exists(y => y.Description.Contains("Changes approved."))).Count()/_listAttachedJobs.Count*100)+"%";
			#endregion
			#region Left Panel
			//Set all completed job percentages
			List<double> listCompletedPercents=new List<double>();
			listCompletedPercents.Add(Math.Round((listCompletedBugJobs.Count()/totalJobsCompleted*100),2));
			textCompletedBugsForRange.Text=listCompletedPercents.Last().ToString("0.00")+"%";
			listCompletedPercents.Add(Math.Round((_listAttachedJobs.Where(x => x.Category==JobCategory.Feature 
				&& x.PhaseCur.In(JobPhase.Documentation,JobPhase.Complete)).Count()/totalJobsCompleted*100),2));
			textCompletedFeaturesForRange.Text=listCompletedPercents.Last().ToString("0.00")+"%";
			listCompletedPercents.Add(Math.Round((_listAttachedJobs.Where(x => x.Category==JobCategory.Enhancement 
				&& x.PhaseCur.In(JobPhase.Documentation,JobPhase.Complete)).Count()/totalJobsCompleted*100),2));
			textCompletedEnhancementsForRange.Text=listCompletedPercents.Last().ToString("0.00")+"%";
			listCompletedPercents.Add(Math.Round((_listAttachedJobs.Where(x => x.Category==JobCategory.InternalRequest 
				&& x.PhaseCur.In(JobPhase.Documentation,JobPhase.Complete)).Count()/totalJobsCompleted*100),2));
			textCompletedInternalRequestsForRange.Text=listCompletedPercents.Last().ToString("0.00")+"%";
			listCompletedPercents.Add(Math.Round((_listAttachedJobs.Where(x => x.Category==JobCategory.HqRequest 
				&& x.PhaseCur.In(JobPhase.Documentation,JobPhase.Complete)).Count()/totalJobsCompleted*100),2));
			textCompletedHQRequestsForRange.Text=listCompletedPercents.Last().ToString("0.00")+"%";
			listCompletedPercents.Add(Math.Round((_listAttachedJobs.Where(x => x.Category==JobCategory.ProgramBridge 
				&& x.PhaseCur.In(JobPhase.Documentation,JobPhase.Complete)).Count()/totalJobsCompleted*100),2));
			textCompletedBridgesForRange.Text=listCompletedPercents.Last().ToString("0.00")+"%";
			DrawCompletedPieChart(listCompletedPercents);
			textJobsComplete.Text=totalJobsCompleted.ToString();
			#endregion
			#region Right Panel
			//Set all remaining job percentages
			List<double> listRemainingPercents=new List<double>();
			listRemainingPercents.Add(Math.Round((listRemainingBugJobs.Count()/totalJobsRemaining*100),2));
			textRemainingBugPercent.Text=listRemainingPercents.Last().ToString("0.00")+"%";
			listRemainingPercents.Add(Math.Round((_listAttachedJobs.Where(x => x.Category==JobCategory.Feature 
				&& x.PhaseCur.In(JobPhase.Concept,JobPhase.Definition,JobPhase.Quote,JobPhase.Development)).Count()/totalJobsRemaining*100),2));
			textRemainingFeaturePercent.Text=listRemainingPercents.Last().ToString("0.00")+"%";
			listRemainingPercents.Add(Math.Round((_listAttachedJobs.Where(x => x.Category==JobCategory.Enhancement 
				&& x.PhaseCur.In(JobPhase.Concept,JobPhase.Definition,JobPhase.Quote,JobPhase.Development)).Count()/totalJobsRemaining*100),2));
			textRemainingEnhancementPercent.Text=listRemainingPercents.Last().ToString("0.00")+"%";
			listRemainingPercents.Add(Math.Round((_listAttachedJobs.Where(x => x.Category==JobCategory.InternalRequest 
				&& x.PhaseCur.In(JobPhase.Concept,JobPhase.Definition,JobPhase.Quote,JobPhase.Development)).Count()/totalJobsRemaining*100),2));
			textRemainingInternalRequestPercent.Text=listRemainingPercents.Last().ToString("0.00")+"%";
			listRemainingPercents.Add(Math.Round((_listAttachedJobs.Where(x => x.Category==JobCategory.HqRequest 
				&& x.PhaseCur.In(JobPhase.Concept,JobPhase.Definition,JobPhase.Quote,JobPhase.Development)).Count()/totalJobsRemaining*100),2));
			textRemainingHQRequestPercent.Text=listRemainingPercents.Last().ToString("0.00")+"%";
			listRemainingPercents.Add(Math.Round((_listAttachedJobs.Where(x => x.Category==JobCategory.ProgramBridge 
				&& x.PhaseCur.In(JobPhase.Concept,JobPhase.Definition,JobPhase.Quote,JobPhase.Development)).Count()/totalJobsRemaining*100),2));
			textRemainingBridgePercent.Text=listRemainingPercents.Last().ToString("0.00")+"%";
			DrawRemainingPieChart(listRemainingPercents);
			textJobsRemaining.Text=(totalJobsRemaining-listRemainingBugJobs.Count).ToString();//Don't count bugs here
			#endregion
			#region Bottom Panel
			List<Job> listStaleBugs=listRemainingBugJobs.FindAll(x => x.ListJobTimeLogs.Count>0?x.ListJobTimeLogs.Select(y => y.DateTStamp).Max()<DateTime.Today.AddDays(-5):x.DateTimeEntry<DateTime.Today.AddDays(-5))
				.OrderBy(x => x.ListJobTimeLogs.Count>0?x.ListJobTimeLogs.Select(y => y.DateTStamp).Max():x.DateTimeEntry).ToList();
			gridBugJobs.Title=listRemainingBugJobs.Count()+" Bugs ("+listStaleBugs.Count()+" Stale)";
			FillGridOldBugs(listStaleBugs);
			#endregion
		}
示例#2
0
        ///<summary>The DataTable used to fill the grid will only be refreshed from the db if isFromDb is true.  Otherwise the grid will be refilled using
        ///the existing table.  Only get from the db on load or if the Refresh button is pressed, not when the user is selecting the clinic(s).</summary>
        private void FillGrid(bool isFromDb = false)
        {
            Cursor = Cursors.WaitCursor;
            if (isFromDb)
            {
                _charger.FillCharges(_listUserClinics);
            }
            List <long> listSelectedClinicNums = listClinics.SelectedIndices.OfType <int>().Select(x => _listUserClinics[x].ClinicNum).ToList();
            List <RecurringChargeData> listChargesCur;

            if (PrefC.HasClinicsEnabled)
            {
                listChargesCur = _charger.ListRecurringChargeData.Where(x => listSelectedClinicNums.Contains(x.RecurringCharge.ClinicNum)).ToList();
            }
            else
            {
                listChargesCur = _charger.ListRecurringChargeData;
            }
            gridMain.BeginUpdate();
            gridMain.ListGridColumns.Clear();
            gridMain.ListGridColumns.Add(new GridColumn(Lan.g("TableRecurring", "PatNum"), 55));
            gridMain.ListGridColumns.Add(new GridColumn(Lan.g("TableRecurring", "Name"), PrefC.HasClinicsEnabled?190:220));
            if (PrefC.HasClinicsEnabled)
            {
                gridMain.ListGridColumns.Add(new GridColumn(Lan.g("TableRecurring", "Clinic"), 65));
            }
            gridMain.ListGridColumns.Add(new GridColumn(Lan.g("TableRecurring", "Date"), PrefC.HasClinicsEnabled?80:80, HorizontalAlignment.Right));
            gridMain.ListGridColumns.Add(new GridColumn(Lan.g("TableRecurring", "Family Bal"), PrefC.HasClinicsEnabled?70:85, HorizontalAlignment.Right));
            gridMain.ListGridColumns.Add(new GridColumn(Lan.g("TableRecurring", "PayPlan Due"), PrefC.HasClinicsEnabled?75:85, HorizontalAlignment.Right));
            gridMain.ListGridColumns.Add(new GridColumn(Lan.g("TableRecurring", "Total Due"), PrefC.HasClinicsEnabled?65:80, HorizontalAlignment.Right));
            gridMain.ListGridColumns.Add(new GridColumn(Lan.g("TableRecurring", "Repeat Amt"), PrefC.HasClinicsEnabled?75:90, HorizontalAlignment.Right));         //RptChrgAmt
            gridMain.ListGridColumns.Add(new GridColumn(Lan.g("TableRecurring", "Charge Amt"), PrefC.HasClinicsEnabled?85:100, HorizontalAlignment.Right));
            if (Programs.HasMultipleCreditCardProgramsEnabled())
            {
                if (Programs.IsEnabled(ProgramName.Xcharge))
                {
                    gridMain.ListGridColumns.Add(new GridColumn("X-Charge", PrefC.HasClinicsEnabled ? 70 : 80, HorizontalAlignment.Center));
                }
                if (Programs.IsEnabled(ProgramName.PayConnect))
                {
                    gridMain.ListGridColumns.Add(new GridColumn("PayConnect", PrefC.HasClinicsEnabled ? 85 : 95, HorizontalAlignment.Center));
                }
                if (Programs.IsEnabled(ProgramName.PaySimple))
                {
                    gridMain.ListGridColumns.Add(new GridColumn("PaySimple", PrefC.HasClinicsEnabled ? 80 : 90, HorizontalAlignment.Center));
                }
            }
            gridMain.ListGridRows.Clear();
            GridRow row;

            foreach (RecurringChargeData chargeCur in listChargesCur)
            {
                row = new GridRow();
                double famBalTotal  = chargeCur.RecurringCharge.FamBal;             //pat bal+payplan due, but if pat bal<0 and payplan due>0 then just payplan due
                double payPlanDue   = chargeCur.RecurringCharge.PayPlanDue;
                double chargeAmt    = chargeCur.RecurringCharge.ChargeAmt;
                double rptChargeAmt = chargeCur.RecurringCharge.RepeatAmt;              //includes repeat charge (from procs if ODHQ) and attached payplan
                row.Cells.Add(chargeCur.RecurringCharge.PatNum.ToString());
                row.Cells.Add(chargeCur.PatName);
                if (PrefC.HasClinicsEnabled)
                {
                    Clinic clinicCur = _listUserClinics.FirstOrDefault(x => x.ClinicNum == chargeCur.RecurringCharge.ClinicNum);
                    row.Cells.Add(clinicCur != null?clinicCur.Description:"");                  //get description from cache if clinics are enabled
                }
                int billingDay = 0;
                if (PrefC.GetBool(PrefName.BillingUseBillingCycleDay))
                {
                    billingDay = chargeCur.BillingCycleDay;
                }
                else
                {
                    billingDay = chargeCur.RecurringChargeDate.Day;
                }
                DateTime startBillingCycle = DateTimeOD.GetMostRecentValidDate(DateTime.Today.Year, DateTime.Today.Month, billingDay);
                if (startBillingCycle > DateTime.Today)
                {
                    startBillingCycle = startBillingCycle.AddMonths(-1);             //Won't give a date with incorrect day.  AddMonths will give the end of the month if needed.
                }
                DateTime dateExcludeIfBefore = PIn.Date(textDate.Text);              //If entry is invalid, all charges will be included because this will be MinDate.
                if (startBillingCycle < dateExcludeIfBefore)
                {
                    continue;                    //Don't show row in grid
                }
                row.Cells.Add(startBillingCycle.ToShortDateString());
                row.Cells.Add(famBalTotal.ToString("c"));
                if (!payPlanDue.IsZero())
                {
                    row.Cells.Add(payPlanDue.ToString("c"));
                }
                else
                {
                    row.Cells.Add("");
                }
                row.Cells.Add(chargeCur.RecurringCharge.TotalDue.ToString("c"));
                row.Cells.Add(rptChargeAmt.ToString("c"));
                row.Cells.Add(chargeAmt.ToString("c"));
                if (!checkHideBold.Checked)
                {
                    double diff = (Math.Max(famBalTotal, 0) + Math.Max(payPlanDue, 0)) - rptChargeAmt;
                    if (diff.IsZero() || (diff < 0 && RecurringCharges.CanChargeWhenNoBal(chargeCur.CanChargeWhenNoBal)))
                    {
                        //don't bold anything
                    }
                    else if (diff > 0)
                    {
                        row.Cells[6].Bold = YN.Yes;                      //"Repeating Amt"
                        row.Cells[7].Bold = YN.Yes;                      //"Charge Amt"
                    }
                    else if (diff < 0)
                    {
                        row.Cells[5].Bold = YN.Yes;                      //"Total Due"
                        row.Cells[7].Bold = YN.Yes;                      //"Charge Amt"
                    }
                }
                if (Programs.HasMultipleCreditCardProgramsEnabled())
                {
                    if (Programs.IsEnabled(ProgramName.Xcharge))
                    {
                        row.Cells.Add(!string.IsNullOrEmpty(chargeCur.XChargeToken) ? "X" : "");
                    }
                    if (Programs.IsEnabled(ProgramName.PayConnect))
                    {
                        row.Cells.Add(!string.IsNullOrEmpty(chargeCur.PayConnectToken) ? "X" : "");
                    }
                    if (Programs.IsEnabled(ProgramName.PaySimple))
                    {
                        row.Cells.Add(!string.IsNullOrEmpty(chargeCur.PaySimpleToken) ? "X" : "");
                    }
                }
                row.Tag = chargeCur;
                gridMain.ListGridRows.Add(row);
            }
            gridMain.EndUpdate();
            labelTotal.Text    = Lan.g(this, "Total=") + gridMain.ListGridRows.Count.ToString();
            labelSelected.Text = Lan.g(this, "Selected=") + gridMain.SelectedIndices.Length.ToString();
            Cursor             = Cursors.Default;
        }
        private void RefreshTopPanel(List <Job> listJobs, DateTime dateStart, DateTime dateEnd)
        {
            //Calculate the three month average per day
            //listJobsNonBugEnhancement is used because we do not want to consider bugs/enhancements (Backport jobs) as part of this version
            List <Job> listCompletedJobs = listJobs.FindAll(x => x.PhaseCur.In(JobPhase.Documentation, JobPhase.Complete) &&
                                                            DateTimeOD.Between(x.ListJobLogs.FirstOrDefault(y => y.Description.Contains("Job implemented"))?.DateTimeEntry ?? DateTime.MinValue, dateStart, dateEnd));
            //We only want incomplete jobs that are marked as current version. This disregards priority.
            List <Job> listRemainingJobs = listJobs.FindAll(x => x.PhaseCur.In(JobPhase.Concept, JobPhase.Definition, JobPhase.Quote, JobPhase.Development) && x.ProposedVersion == JobProposedVersion.Current);
            //Calculate the remaining hours for the version
            double totalRemainingHours = listRemainingJobs.Sum(x => x.HoursEstimate - x.HoursActual);

            totalRemainingHours = totalRemainingHours < 0 ? 0 : totalRemainingHours;
            //Completed hours is only the hours actual. Should not be negative, but I check for it just in case.
            double totalCompletedHours = listCompletedJobs.Sum(x => x.HoursActual);

            totalCompletedHours = totalCompletedHours < 0 ? 0 : totalCompletedHours;
            //Calculate the total hours value for the version.
            //We use the estimate from the remaining jobs since that is the perceived total amount of time it will take.
            //We use the hours actual from complete jobs because we know the job is done and will take no more time than what was taken.
            double totalVersionHours = totalCompletedHours + listRemainingJobs.Sum(x => x.HoursEstimate);

            totalVersionHours = totalVersionHours < 0 ? 0 : totalVersionHours;
            //Calculate work complete percent
            double completionPercentage = ((totalCompletedHours + listRemainingJobs.Sum(x => x.HoursActual)) / totalVersionHours) * 100;

            //Validate that the return is a valid percentage
            if (Double.IsNaN(completionPercentage))
            {
                completionPercentage = 0;
            }
            completionPercentage = completionPercentage >= 100 ? 100 : completionPercentage;
            //Calculate day variables
            double totalDays        = (dateEnd - dateStart).TotalDays;
            double totalDaysElapsed = (DateTime.Today.Date - dateStart).TotalDays;
            double totalDaysLeft    = totalDays - totalDaysElapsed;

            //We don't need to display negative days left
            if (totalDaysLeft < 0)
            {
                totalDaysLeft = 0;
            }
            //Calculate target percent
            int targetValuePercent = (int)(totalDaysElapsed / totalDays * 100);

            if (targetValuePercent > 100)
            {
                targetValuePercent = 100;
            }
            if (targetValuePercent < 0)
            {
                targetValuePercent = 0;
            }
            //Calculate average hours/day of job time for the last 3 months
            double hoursLogged = listJobs.Sum(x => x.ListJobTimeLogs.Where(y => y.DateTStamp.Between(DateTime.Today.AddMonths(-3), DateTime.Today)).Sum(y => y.Hours));
            //hoursReviewed is multiplied by 2 to denote that two engineers time was expended per review
            double hoursReviewed       = listJobs.Sum(x => x.ListJobReviews.Where(y => y.DateTStamp.Between(DateTime.Today.AddMonths(-3), DateTime.Today)).Sum(y => y.Hours)) * 2;
            double hoursCompletePerDay = (hoursLogged + hoursReviewed) / (DateTime.Today - DateTime.Today.AddMonths(-3)).TotalDays;
            //Calculate days remaining
            double daysRemainingEstimate = Math.Round(totalRemainingHours / hoursCompletePerDay, 0);

            //If for some reason we just divided by 0...
            if (Double.IsNaN(daysRemainingEstimate))
            {
                daysRemainingEstimate = 0;
            }
            //Set Panel's Controls
            //Dates
            textStartDate.Text        = _jobSprintCur.DateStart.ToShortDateString();
            textTargetDate.Text       = _jobSprintCur.DateEndTarget.ToShortDateString() + " (" + totalDaysLeft + " days)";
            textProjectedRelease.Text = DateTime.Today.AddDays(daysRemainingEstimate).ToShortDateString() + " (" + Math.Abs(daysRemainingEstimate) + " days)";
            //Work Complete
            textCompletePercentage.Text  = (int)completionPercentage + "%";
            progressComplete.Value       = (int)completionPercentage;
            progressComplete.TargetValue = (int)completionPercentage;          //This could be changed to the target value percent if we want
            //Time elapsed
            textElapsedPercentage.Text  = targetValuePercent + "%";
            progressElapsed.Value       = targetValuePercent;
            progressElapsed.TargetValue = targetValuePercent;
        }
 ///<summary>Calculates the info for the dashboard</summary>
 private void RefreshAll()
 {
     //Validation
     if (_jobSprintCur.DateStart > _jobSprintCur.DateEndTarget)
     {
         return;
     }
     this.Text = _jobSprintCur.Title;
     #region Variables
     DateTime dateStart    = _jobSprintCur.DateStart;
     DateTime dateProgress = DateTime.Today.Date;
     DateTime dateEnd      = _jobSprintCur.DateEndTarget;
     //Distill the _listJobsAll into two job subsets
     List <Job> listJobsNonBugEnhancement = _listJobsAll.FindAll(x => x.Category.In(JobCategory.Feature, JobCategory.InternalRequest, JobCategory.HqRequest, JobCategory.ProgramBridge));
     List <Job> listJobsBugEnhancement    = _listJobsAll.FindAll(x => x.Category.In(JobCategory.Bug, JobCategory.Enhancement));
     //Make the actual lists we will be using
     List <Job> listJobsCompletedNonBugEnhancement = listJobsNonBugEnhancement.FindAll(x => x.PhaseCur.In(JobPhase.Documentation, JobPhase.Complete) &&
                                                                                       DateTimeOD.Between(x.ListJobLogs.FirstOrDefault(y => y.Description.Contains("Job implemented"))?.DateTimeEntry ?? DateTime.MinValue, dateStart, dateEnd));
     List <Job> listCompletedNonBugJobsThreeMonths = _listJobsAll.FindAll(x => x.PhaseCur.In(JobPhase.Documentation, JobPhase.Complete) && x.Category.In(JobCategory.Feature, JobCategory.InternalRequest, JobCategory.HqRequest, JobCategory.ProgramBridge, JobCategory.Enhancement) &&
                                                                          DateTimeOD.Between(x.ListJobLogs.FirstOrDefault(y => y.Description.Contains("Job implemented"))?.DateTimeEntry ?? DateTime.MinValue, DateTime.Today.AddMonths(-3), DateTime.Today));
     List <Job> listRemainingNonBugJobs   = listJobsNonBugEnhancement.FindAll(x => x.PhaseCur.In(JobPhase.Concept, JobPhase.Definition, JobPhase.Quote, JobPhase.Development) && x.ProposedVersion == JobProposedVersion.Current);
     List <Job> listCompletedBackportJobs = listJobsBugEnhancement.FindAll(x => x.PhaseCur.In(JobPhase.Documentation, JobPhase.Complete) &&
                                                                           x.ListJobLinks.Count(y => y.LinkType == JobLinkType.Bug) > 0 &&
                                                                           DateTimeOD.Between(x.ListJobLogs.FirstOrDefault(y => y.Description.Contains("Job implemented"))?.DateTimeEntry ?? DateTime.MinValue, dateStart, dateEnd));
     List <Job> listRemainingBugJobs = listJobsBugEnhancement.FindAll(x => x.Category == JobCategory.Bug && x.PhaseCur.In(JobPhase.Concept, JobPhase.Definition, JobPhase.Quote, JobPhase.Development) &&
                                                                      x.ListJobLinks.Count(y => y.LinkType == JobLinkType.Bug) > 0);
     List <Job> listRemainingEnhancementJobs = listJobsBugEnhancement.FindAll(x => x.Category == JobCategory.Enhancement &&
                                                                              x.PhaseCur.In(JobPhase.Concept, JobPhase.Definition, JobPhase.Quote, JobPhase.Development) &&
                                                                              x.ProposedVersion == JobProposedVersion.Current);
     double totalDays        = (dateEnd - dateStart).TotalDays;
     double totalDaysElapsed = (dateProgress - dateStart).TotalDays;
     double totalDaysLeft    = totalDays - totalDaysElapsed;
     double jobPercent       = _jobSprintCur.JobPercent;
     double hoursComplete    = listJobsCompletedNonBugEnhancement.Sum(x => x.HoursActual) + listRemainingNonBugJobs.Sum(x => x.HoursActual);
     double hoursTotal       = listJobsCompletedNonBugEnhancement.Sum(x => x.HoursActual) + listRemainingNonBugJobs.Sum(x => x.HoursEstimate);
     double hoursRemaining   = hoursTotal - hoursComplete > 0?hoursTotal - hoursComplete:0;
     #endregion
     RefreshTopPanel(listJobsNonBugEnhancement, dateStart, dateEnd);
     #region Left Upper Panel
     //Set all completed job percentages
     List <double> listCompletedPercents = new List <double>();
     //Cast one to a double so the int doesn't truncate to 0.
     double percent = (double)(listJobsCompletedNonBugEnhancement.Where(x => x.Category == JobCategory.Feature).Count()) / listJobsCompletedNonBugEnhancement.Count() * 100;
     listCompletedPercents.Add(Math.Round(percent, 2));
     textCompletedFeaturesForRange.Text = percent.ToString("0.00") + "%";
     percent = (double)(listJobsCompletedNonBugEnhancement.Where(x => x.Category == JobCategory.HqRequest).Count()) / listJobsCompletedNonBugEnhancement.Count() * 100;
     listCompletedPercents.Add(Math.Round(percent, 2));
     textCompletedHQRequestsForRange.Text = percent.ToString("0.00") + "%";
     percent = (double)(listJobsCompletedNonBugEnhancement.Where(x => x.Category == JobCategory.InternalRequest).Count()) / listJobsCompletedNonBugEnhancement.Count() * 100;
     listCompletedPercents.Add(Math.Round(percent, 2));
     textCompletedInternalRequestsForRange.Text = percent.ToString("0.00") + "%";
     percent = (double)(listJobsCompletedNonBugEnhancement.Where(x => x.Category == JobCategory.ProgramBridge).Count()) / listJobsCompletedNonBugEnhancement.Count() * 100;
     listCompletedPercents.Add(Math.Round(percent, 2));
     textCompletedBridgesForRange.Text = percent.ToString("0.00") + "%";
     DrawCompletedPieChart(listCompletedPercents);
     textJobsComplete.Text = listJobsCompletedNonBugEnhancement.Count().ToString();
     #endregion
     #region Right Upper Panel
     //Set all remaining job percentages
     List <double> listRemainingPercents = new List <double>();
     percent = (double)(listRemainingNonBugJobs.Where(x => x.Category == JobCategory.Feature).Count()) / listRemainingNonBugJobs.Count() * 100;
     listRemainingPercents.Add(Math.Round(percent, 2));
     textRemainingFeaturePercent.Text = percent.ToString("0.00") + "%";
     percent = (double)(listRemainingNonBugJobs.Where(x => x.Category == JobCategory.HqRequest).Count()) / listRemainingNonBugJobs.Count() * 100;
     listRemainingPercents.Add(Math.Round(percent, 2));
     textRemainingHQRequestPercent.Text = percent.ToString("0.00") + "%";
     percent = (double)(listRemainingNonBugJobs.Where(x => x.Category == JobCategory.InternalRequest).Count()) / listRemainingNonBugJobs.Count() * 100;
     listRemainingPercents.Add(Math.Round(percent, 2));
     textRemainingInternalRequestPercent.Text = percent.ToString("0.00") + "%";
     percent = (double)(listRemainingNonBugJobs.Where(x => x.Category == JobCategory.ProgramBridge).Count()) / listRemainingNonBugJobs.Count() * 100;
     listRemainingPercents.Add(Math.Round(percent, 2));
     textRemainingBridgePercent.Text = percent.ToString("0.00") + "%";
     DrawRemainingPieChart(listRemainingPercents);
     textJobsRemaining.Text = listRemainingNonBugJobs.Count().ToString();
     #endregion
     #region Left Lower Panel
     //Set all completed backport percentages
     List <double> listCompletedBackportPercents = new List <double>();
     percent = (double)(listCompletedBackportJobs.FindAll(x => x.Category == JobCategory.Bug).Count()) / listCompletedBackportJobs.Count() * 100;
     listCompletedBackportPercents.Add(Math.Round(percent, 2));
     textCompletedBugPercentage.Text = percent.ToString("0.00") + "%";
     percent = (double)(listCompletedBackportJobs.FindAll(x => x.Category == JobCategory.Enhancement).Count()) / listCompletedBackportJobs.Count() * 100;
     listCompletedBackportPercents.Add(Math.Round(percent, 2));
     textCompletedEnhancementPercentage.Text = percent.ToString("0.00") + "%";
     DrawCompletedBackportPieChart(listCompletedBackportPercents);
     textCompletedBackports.Text = listCompletedBackportJobs.Count().ToString();
     #endregion
     #region Right Lower Panel
     //Set all remaining backport percentages
     List <double> listRemainingBackportPercents = new List <double>();
     int           countBugEnhancement           = listRemainingBugJobs.Count() + listRemainingEnhancementJobs.Count();
     percent = (double)(listRemainingBugJobs.Count()) / countBugEnhancement * 100;
     listRemainingBackportPercents.Add(Math.Round(percent, 2));
     textRemainingBugPercentage.Text = percent.ToString("0.00") + "%";
     percent = (double)(listRemainingEnhancementJobs.Count()) / countBugEnhancement * 100;
     listRemainingBackportPercents.Add(Math.Round(percent, 2));
     textRemainingEnhancementPercentage.Text = percent.ToString("0.00") + "%";
     DrawRemainingBackportPieChart(listRemainingBackportPercents);
     textRemainingBackports.Text = countBugEnhancement.ToString();
     #endregion
     #region Bottom Panel
     List <Job> listStaleBugs = listRemainingBugJobs.FindAll(x => x.ListJobTimeLogs.Count > 0 ? x.ListJobTimeLogs.Select(y => y.DateTStamp).Max() < DateTime.Today.AddDays(-7) : x.DateTimeEntry < DateTime.Today.AddDays(-7))
                                .OrderBy(x => x.ListJobTimeLogs.Count > 0 ? x.ListJobTimeLogs.Select(y => y.DateTStamp).Max() : x.DateTimeEntry).ToList();
     List <Job> listStaleEnhancements = listRemainingEnhancementJobs.FindAll(x => x.ListJobTimeLogs.Count > 0 ? x.ListJobTimeLogs.Select(y => y.DateTStamp).Max() < DateTime.Today.AddDays(-7) : x.DateTimeEntry < DateTime.Today.AddDays(-7))
                                        .OrderBy(x => x.ListJobTimeLogs.Count > 0 ? x.ListJobTimeLogs.Select(y => y.DateTStamp).Max() : x.DateTimeEntry).ToList();
     gridBugJobs.Title         = listRemainingBugJobs.Count() + " Bugs (" + listStaleBugs.Count() + " Stale)";
     gridEnhancementJobs.Title = listRemainingEnhancementJobs.Count() + " Enhancements (" + listStaleEnhancements.Count() + " Stale)";
     FillGridOldBugs(listStaleBugs);
     FillGridOldEnhancements(listStaleEnhancements);
     #endregion
 }
示例#5
0
        private void FillGrid()
        {
            long clinicNum = 0;

            //if clinics are not enabled, comboClinic.SelectedIndex will be -1, so clinicNum will be 0 and list will not be filtered by clinic
            if (Security.CurUser.ClinicIsRestricted && comboClinics.SelectedIndex > -1)
            {
                clinicNum = _listClinics[comboClinics.SelectedIndex].ClinicNum;
            }
            else if (comboClinics.SelectedIndex > 0)                                //if user is not restricted, clinicNum will be 0 and the query will get all clinic data
            {
                clinicNum = _listClinics[comboClinics.SelectedIndex - 1].ClinicNum; //if user is not restricted, comboClinic will contain "All" so minus 1
            }
            int clinicWidth  = 80;
            int patientWidth = 180;
            int carrierWidth = 220;

            if (PrefC.HasClinicsEnabled)
            {
                patientWidth = 140;
                carrierWidth = 200;
            }
            gridMain.BeginUpdate();
            gridMain.Columns.Clear();
            ODGridColumn col = new ODGridColumn(Lan.g("TableAutoOrthoClaims", "Patient"), patientWidth);

            gridMain.Columns.Add(col);
            col = new ODGridColumn(Lan.g("TableAutoOrthoClaims", "Carrier"), carrierWidth);
            gridMain.Columns.Add(col);
            col = new ODGridColumn(Lan.g("TableAutoOrthoClaims", "TxMonths"), 70);
            gridMain.Columns.Add(col);
            col = new ODGridColumn(Lan.g("TableAutoOrthoClaims", "Banding"), 80, HorizontalAlignment.Center);
            gridMain.Columns.Add(col);
            col = new ODGridColumn(Lan.g("TableAutoOrthoClaims", "MonthsRem"), 100);
            gridMain.Columns.Add(col);
            col = new ODGridColumn(Lan.g("TableAutoOrthoClaims", "#Sent"), 60);
            gridMain.Columns.Add(col);
            col = new ODGridColumn(Lan.g("TableAutoOrthoClaims", "LastSent"), 80, HorizontalAlignment.Center);
            gridMain.Columns.Add(col);
            col = new ODGridColumn(Lan.g("TableAutoOrthoClaims", "NextClaim"), 80, HorizontalAlignment.Center);
            gridMain.Columns.Add(col);
            if (PrefC.HasClinicsEnabled)              //clinics is turned on
            {
                col = new ODGridColumn(Lan.g("TableAutoOrthoClaims", "Clinic"), clinicWidth, HorizontalAlignment.Center);
                gridMain.Columns.Add(col);
            }
            gridMain.Rows.Clear();
            ODGridRow row;

            foreach (DataRow rowCur in _tableOutstandingAutoClaims.Rows)
            {
                //need a check for if clinics is on here
                if (PrefC.HasClinicsEnabled &&             //Clinics are enabled
                    (Security.CurUser.ClinicIsRestricted || comboClinics.SelectedIndex != 0) &&                   //"All" is not selected
                    clinicNum != PIn.Long(rowCur["ClinicNum"].ToString()))                        //currently selected clinic doesn't match the row's clinic
                {
                    continue;
                }
                row = new ODGridRow();
                DateTime   dateLastSeen   = PIn.Date(rowCur["LastSent"].ToString());
                DateTime   dateBanding    = PIn.Date(rowCur["DateBanding"].ToString());
                DateTime   dateNextClaim  = PIn.Date(rowCur["OrthoAutoNextClaimDate"].ToString());
                DateTimeOD dateTMonthsRem = new DateTimeOD(PIn.Date(rowCur["DateBanding"].ToString()).AddMonths(PIn.Int(rowCur["MonthsTreat"].ToString())), DateTimeOD.Today);
                row.Cells.Add(PIn.String(rowCur["Patient"].ToString()));
                row.Cells.Add(PIn.String(rowCur["CarrierName"].ToString()));
                row.Cells.Add(PIn.String(rowCur["MonthsTreat"].ToString()));
                row.Cells.Add(dateBanding.Year < 1880 ? "" : dateBanding.ToShortDateString()); //add blank if there is no banding
                if (dateBanding.Year < 1880)                                                   //add blank if there is no banding
                {
                    row.Cells.Add("");
                }
                else
                {
                    row.Cells.Add(((dateTMonthsRem.YearsDiff * 12) + dateTMonthsRem.MonthsDiff) + " " + Lan.g(this, "months")
                                  + ", " + dateTMonthsRem.DaysDiff + " " + Lan.g(this, "days"));
                }
                row.Cells.Add(PIn.String(rowCur["NumSent"].ToString()));
                row.Cells.Add(dateLastSeen.Year < 1880 ? "" : dateLastSeen.ToShortDateString());
                row.Cells.Add(dateNextClaim.Year < 1880 ? "" : dateNextClaim.ToShortDateString());
                if (PrefC.HasClinicsEnabled)                  //clinics is turned on
                //Use the long list of clinics so that hidden clinics can be shown for unrestricted users.
                {
                    row.Cells.Add(Clinics.GetAbbr(PIn.Long(rowCur["ClinicNum"].ToString())));
                }
                row.Tag = rowCur;
                gridMain.Rows.Add(row);
            }
            gridMain.EndUpdate();
        }
示例#6
0
        private void butGenerateClaims_Click(object sender, EventArgs e)
        {
            if (gridMain.SelectedIndices.Count() < 1)
            {
                MsgBox.Show(this, "Please select the rows for which you would like to create procedures and claims.");
                return;
            }
            if (!MsgBox.Show(this, MsgBoxButtons.YesNo, "Are you sure you want to generate claims and procedures for all patients and insurance plans?"))
            {
                return;
            }
            List <long> listPlanNums    = new List <long>();
            List <long> listPatPlanNums = new List <long>();
            List <long> listInsSubNums  = new List <long>();

            for (int i = 0; i < gridMain.SelectedIndices.Count(); i++)
            {
                DataRow rowCur = (DataRow)gridMain.Rows[gridMain.SelectedIndices[i]].Tag;
                listPlanNums.Add(PIn.Long(rowCur["PlanNum"].ToString()));
                listPatPlanNums.Add(PIn.Long(rowCur["PatPlanNum"].ToString()));
                listInsSubNums.Add(PIn.Long(rowCur["InsSubNum"].ToString()));
            }
            List <InsPlan> listSelectedInsPlans = InsPlans.GetPlans(listPlanNums);
            List <PatPlan> listSelectedPatPlans = PatPlans.GetPatPlans(listPatPlanNums);
            List <InsSub>  listSelectedInsSubs  = InsSubs.GetMany(listInsSubNums);
            List <DataRow> rowsSucceeded        = new List <DataRow>();
            int            rowsFailed           = 0;
            List <Benefit> listBenefitsAll      = Benefits.Refresh(listSelectedPatPlans, listSelectedInsSubs);

            for (int i = 0; i < gridMain.SelectedIndices.Count(); i++)
            {
                try {
                    DataRow     rowCur        = (DataRow)gridMain.Rows[gridMain.SelectedIndices[i]].Tag;
                    long        patNumCur     = PIn.Long(rowCur["PatNum"].ToString());
                    Patient     patCur        = Patients.GetPat(patNumCur);
                    PatientNote patNoteCur    = PatientNotes.Refresh(patNumCur, patCur.Guarantor);
                    long        codeNumCur    = PIn.Long(rowCur["AutoCodeNum"].ToString());
                    long        provNumCur    = PIn.Long(rowCur["ProvNum"].ToString());
                    long        clinicNumCur  = PIn.Long(rowCur["ClinicNum"].ToString());
                    long        insPlanNumCur = PIn.Long(rowCur["PlanNum"].ToString());
                    long        patPlanNumCur = PIn.Long(rowCur["PatPlanNum"].ToString());
                    long        insSubNumCur  = PIn.Long(rowCur["InsSubNum"].ToString());
                    int         monthsTreat   = PIn.Int(rowCur["MonthsTreat"].ToString());
                    DateTime    dateDue       = PIn.Date(rowCur["OrthoAutoNextClaimDate"].ToString());
                    //for each selected row
                    //create a procedure
                    //Procedures.CreateProcForPat(patNumCur,codeNumCur,"","",ProcStat.C,provNumCur);
                    Procedure      proc        = Procedures.CreateOrthoAutoProcsForPat(patNumCur, codeNumCur, provNumCur, clinicNumCur, dateDue);
                    InsPlan        insPlanCur  = InsPlans.GetPlan(insPlanNumCur, listSelectedInsPlans);
                    PatPlan        patPlanCur  = listSelectedPatPlans.FirstOrDefault(x => x.PatPlanNum == patPlanNumCur);
                    InsSub         insSubCur   = listSelectedInsSubs.FirstOrDefault(x => x.InsSubNum == insSubNumCur);
                    List <Benefit> benefitList = listBenefitsAll.FindAll(x => x.PatPlanNum == patPlanCur.PatPlanNum || x.PlanNum == insSubCur.PlanNum);
                    //create a claimproc
                    List <ClaimProc> listClaimProcs = new List <ClaimProc>();
                    Procedures.ComputeEstimates(proc, patNumCur, ref listClaimProcs, true, new List <InsPlan> {
                        insPlanCur
                    },
                                                new List <PatPlan> {
                        patPlanCur
                    }, benefitList, null, null, true, patCur.Age, new List <InsSub> {
                        insSubCur
                    }, isForOrtho: true);
                    //make the feebilled == the insplan feebilled or patplan feebilled
                    double feebilled = patPlanCur.OrthoAutoFeeBilledOverride == -1 ? insPlanCur.OrthoAutoFeeBilled : patPlanCur.OrthoAutoFeeBilledOverride;
                    //create a claim with that claimproc
                    string claimType = "";
                    switch (patPlanCur.Ordinal)
                    {
                    case 1:
                        claimType = "P";
                        break;

                    case 2:
                        claimType = "S";
                        break;
                    }
                    DateTimeOD dateTMonthsRem = new DateTimeOD(PIn.Date(rowCur["DateBanding"].ToString()).AddMonths(PIn.Int(rowCur["MonthsTreat"].ToString())), DateTimeOD.Today);
                    Claims.CreateClaimForOrthoProc(claimType, patPlanCur, insPlanCur, insSubCur,
                                                   ClaimProcs.GetForProcWithOrdinal(proc.ProcNum, patPlanCur.Ordinal), proc, feebilled, PIn.Date(rowCur["DateBanding"].ToString()),
                                                   PIn.Int(rowCur["MonthsTreat"].ToString()), ((dateTMonthsRem.YearsDiff * 12) + dateTMonthsRem.MonthsDiff));
                    PatPlans.IncrementOrthoNextClaimDates(patPlanCur, insPlanCur, monthsTreat, patNoteCur);
                    rowsSucceeded.Add(rowCur);
                    SecurityLogs.MakeLogEntry(Permissions.ProcComplCreate, patCur.PatNum
                                              , Lan.g(this, "Automatic ortho procedure and claim generated for") + " " + dateDue.ToShortDateString());
                }
                catch (Exception) {
                    rowsFailed++;
                }
            }
            string message = Lan.g(this, "Done.") + " " + Lan.g(this, "There were") + " " + rowsSucceeded.Count + " "
                             + Lan.g(this, "claim(s) generated and") + " " + rowsFailed + " " + Lan.g(this, "failures") + ".";

            MessageBox.Show(message);
            foreach (DataRow row in rowsSucceeded)
            {
                _tableOutstandingAutoClaims.Rows.Remove(row);
            }
            FillGrid();
        }
示例#7
0
        ///<summary>Same as FillOrtho() in the ContrAccount.</summary>
        private void FillOrtho()
        {
            gridOrtho.BeginUpdate();
            gridOrtho.Columns.Clear();
            gridOrtho.Columns.Add(new ODGridColumn("", (gridOrtho.Width / 2) - 20, HorizontalAlignment.Right));
            gridOrtho.Columns.Add(new ODGridColumn("", (gridOrtho.Width / 2) + 20, HorizontalAlignment.Left));
            gridOrtho.Rows.Clear();
            ODGridRow row            = new ODGridRow();
            DateTime  firstOrthoProc = Procedures.GetFirstOrthoProcDate(_patNoteCur);

            if (firstOrthoProc != DateTime.MinValue)
            {
                row.Cells.Add(Lan.g(this, "Total Tx Time") + ": ");              //Number of Years/Months/Days since the first ortho procedure on this account
                DateTimeOD dateTOD     = new DateTimeOD(firstOrthoProc, DateTimeOD.Today);
                string     strDateDiff = "";
                if (dateTOD.YearsDiff != 0)
                {
                    strDateDiff += dateTOD.YearsDiff + " " + Lan.g(this, "year" + (dateTOD.YearsDiff == 1 ? "" : "s"));
                }
                if (dateTOD.MonthsDiff != 0)
                {
                    if (strDateDiff != "")
                    {
                        strDateDiff += ", ";
                    }
                    strDateDiff += dateTOD.MonthsDiff + " " + Lan.g(this, "month" + (dateTOD.MonthsDiff == 1 ? "" : "s"));
                }
                if (dateTOD.DaysDiff != 0 || strDateDiff == "")
                {
                    if (strDateDiff != "")
                    {
                        strDateDiff += ", ";
                    }
                    strDateDiff += dateTOD.DaysDiff + " " + Lan.g(this, "day" + (dateTOD.DaysDiff == 1 ? "" : "s"));
                }
                row.Cells.Add(strDateDiff);
                gridOrtho.Rows.Add(row);
                row = new ODGridRow();
                row.Cells.Add(Lan.g(this, "Date Start") + ": ");              //Date of the first ortho procedure on this account
                row.Cells.Add(firstOrthoProc.ToShortDateString());
                gridOrtho.Rows.Add(row);

                row = new ODGridRow();
                row.Cells.Add(Lan.g(this, "Tx Months Total") + ": ");              //this patient's OrthoClaimMonthsTreatment, or the practice default if 0.
                int txMonthsTotal = (_patNoteCur.OrthoMonthsTreatOverride == -1?PrefC.GetByte(PrefName.OrthoDefaultMonthsTreat):_patNoteCur.OrthoMonthsTreatOverride);
                row.Cells.Add(txMonthsTotal.ToString());
                gridOrtho.Rows.Add(row);

                row = new ODGridRow();
                int txTimeInMonths = dateTOD.YearsDiff * 12 + dateTOD.MonthsDiff + (dateTOD.DaysDiff < 15? 0: 1);
                row.Cells.Add(Lan.g(this, "Months in Treatment") + ": ");              //idk what the difference between this and 'Total Tx Time' is.
                row.Cells.Add(txTimeInMonths.ToString());
                gridOrtho.Rows.Add(row);

                row = new ODGridRow();
                row.Cells.Add(Lan.g(this, "Months Rem") + ": ");              //Months Total - Total Tx Time
                row.Cells.Add(Math.Max(0, txMonthsTotal - txTimeInMonths).ToString());
                gridOrtho.Rows.Add(row);
            }
            else
            {
                row = new ODGridRow();
                row.Cells.Add("");                 //idk what the difference between this and 'Total Tx Time' is.
                row.Cells.Add(Lan.g(this, "No ortho procedures charted") + ".");
                gridOrtho.Rows.Add(row);
            }
            gridOrtho.EndUpdate();
        }
        ///<summary>Go through the transaction dictionary created in CreateProcedureLogs() to edit repeat charges as needed.
        ///Returns the note for the newly generated repeat charge.</summary>
        private void ZeroOutRepeatingCharge(ProcedureCode procCur, List <AvaTax.TransQtyAmt> listCurTrans)
        {
            Commlog prepaymentCommlog = new Commlog();

            prepaymentCommlog.PatNum         = _patCur.PatNum;
            prepaymentCommlog.SentOrReceived = CommSentOrReceived.Received;
            prepaymentCommlog.CommDateTime   = DateTime.Now;
            prepaymentCommlog.CommType       = Commlogs.GetTypeAuto(CommItemTypeAuto.FIN);
            prepaymentCommlog.Mode_          = CommItemMode.None;
            prepaymentCommlog.Note           = "";//Appended to below.
            prepaymentCommlog.UserNum        = Security.CurUser.UserNum;
            string note = "From PrepaymentTool: \r\n";
            bool   hasBeenBilledThisMonth = (DateTimeOD.Today.Day >= _patCur.BillingCycleDay);
            //Get all applicable repeat charges.
            List <RepeatCharge> listRcForProc = _listRcForPat.FindAll(x => x.ProcCode == procCur.ProcCode && x.IsEnabled);
            //Get number of months new repeat charge will be for.
            int numMonths = listCurTrans.Sum(x => x.qty);
            //Create repeat charge, taken from ContrAccount.cs
            RepeatCharge rcNew = new RepeatCharge();

            rcNew.PatNum         = _patCur.PatNum;
            rcNew.ProcCode       = procCur.ProcCode;
            rcNew.ChargeAmt      = 0;
            rcNew.IsEnabled      = true;
            rcNew.CopyNoteToProc = true;
            //Build dates using billing day so the patient doesn't have gaps in their repeat charges.
            DateTime dateBillThisMonth = DateTimeOD.GetMostRecentValidDate(DateTime.Today.Year, DateTime.Today.Month, _patCur.BillingCycleDay);

            if (hasBeenBilledThisMonth)
            {
                //Current month has been billed, push new repeat charge out a month.
                rcNew.DateStart = dateBillThisMonth.AddMonths(1);
                rcNew.DateStop  = dateBillThisMonth.AddMonths(numMonths);
            }
            else
            {
                //Current month has not been billed yet, include on this repeat charge.
                rcNew.DateStart = dateBillThisMonth;
                rcNew.DateStop  = dateBillThisMonth.AddMonths(numMonths - 1);
            }
            //Use the stop date to update the Note as requested by Accounting.
            DatePrepaidThrough = rcNew.DateStop.AddMonths(1).AddDays(-1);
            rcNew.Note         = _prepaidThroughNote;
            //Edit exisiting repeat charge start/stop dates.
            foreach (RepeatCharge rcExisting in listRcForProc)
            {
                if (rcExisting.DateStop.Year > 1880 && rcExisting.DateStop < DateTimeOD.Today)
                {
                    continue;                    //The charge has a stop date in the past (has been disabled).
                }
                if (rcExisting.DateStop.Year > 1880 && rcExisting.DateStop <= DateTimeOD.Today.AddMonths(numMonths))
                {
                    rcExisting.DateStop  = DateTimeOD.Today;
                    rcExisting.IsEnabled = false;
                    //This repeat charge will never be used again due to the prepayment we are creating right now.  Disable and add note to commlog for history.
                    note += "Disabled repeat charge with Rate: " + POut.Double(rcExisting.ChargeAmt) + " for Code: " + POut.String(rcExisting.ProcCode)
                            + " Start Date: " + POut.Date(rcExisting.DateStart) + " Stop Date: " + POut.Date(rcExisting.DateStop) + "\r\n";
                    RepeatCharges.Update(rcExisting);
                    continue;
                }
                //Need to push start date of existing repeat charge forward one month past the new repeat charge (if charge months overlap).
                DateTime dateNext = rcNew.DateStop.AddMonths(1);
                if (dateNext > rcExisting.DateStart)                 //Only change if needed.
                {
                    note += "Edited Start Date for repeat charge from: " + POut.Date(rcExisting.DateStart) + " to: " + POut.Date(dateNext) +
                            " Code: " + POut.String(rcExisting.ProcCode) + " Rate: " + POut.Double(rcExisting.ChargeAmt) + "\r\n";
                    //Change to billing day to make sure it matches other repeat charges.
                    rcExisting.DateStart = dateNext;
                    RepeatCharges.Update(rcExisting);
                }
            }
            //Insert the new repeat charge.
            prepaymentCommlog.Note = note;
            Commlogs.Insert(prepaymentCommlog);
            RepeatCharges.Insert(rcNew);
        }
        ///<summary>Looks in the patient's repeating charges for a rate to use.  If the patient does not have a repeat charge setup
        ///for the procedurecode that is being added then a procedurecharge will not be created.
        ///This is then used to create one or more procedurecharges.</summary>
        private void CreateProcedureCharge(ProcedureCode ProcCode, int count, bool isNew = true)
        {
            List <RepeatCharge>    listRcForProc        = _listRcForPat.FindAll(x => x.ProcCode == ProcCode.ProcCode && x.IsEnabled);
            List <ProcedureCharge> listProcChargeInGrid = _listProcedureCharge.FindAll(x => x.ProcCode == ProcCode);

            if (listRcForProc.Count == 1)
            {
                //Discussed with accounting dept.  If there is only one repeat charge for a proc on an account it should never have a stop date.
                //If for some reason there is a stop date, it is a very special case that we can't currently handle with the prepayment tool.
                int index = _listProcedureCharge.FindIndex(x => x.BaseFee == listRcForProc[0].ChargeAmt && x.ProcCode == ProcCode);
                //Does not exist in our list, make a new one.
                if (index == -1)
                {
                    ProcedureCharge procCharge = new ProcedureCharge(ProcCode, listRcForProc.FirstOrDefault().ChargeAmt);
                    procCharge.ProcCount = count;
                    procCharge.Calc();
                    _listProcedureCharge.Add(procCharge);
                }
                else
                {
                    _listProcedureCharge[index].ProcCount += count;
                }
            }
            else if (listRcForProc.Count >= 2)
            {
                int remainder = count;
                foreach (RepeatCharge charge in listRcForProc)
                {
                    if (remainder <= 0)                   //Nothing left to add, kick out of loop.
                    {
                        break;
                    }
                    if (charge.DateStop.Year > 1880 && charge.DateStop < DateTimeOD.Today)
                    {
                        continue;                        //The charge has a stop date in the past (has been disabled).
                    }
                    //Look for existing procedurecharge.
                    int index = _listProcedureCharge.FindIndex(x => x.BaseFee == charge.ChargeAmt && x.ProcCode == ProcCode && x.HasReachedStopDate == false);
                    //Does not exist in our list, make a new one.
                    if (index == -1)
                    {
                        ProcedureCharge procCharge = new ProcedureCharge(ProcCode, charge.ChargeAmt);
                        //See if the months we are adding extends beyond this repeat charge's stop date.
                        DateTime dateToUse = charge.DateStart;
                        //Check if we should use start date or today.  Prevent old charges.
                        if (DateTimeOD.Today > charge.DateStart)
                        {
                            dateToUse = DateTimeOD.Today;
                        }
                        if (dateToUse.AddMonths(remainder) > charge.DateStop && charge.DateStop.Year > 1880)
                        {
                            procCharge.HasReachedStopDate = true;
                            //Difference is number of months between today and the stop date, this will become the count for our current procedurecharge
                            int difference = ((charge.DateStop.Year - dateToUse.Year) * 12) + (charge.DateStop.Month - dateToUse.Month);
                            if (DateTimeOD.Today < DateTimeOD.GetMostRecentValidDate(dateToUse.Year, dateToUse.Month, _patCur.BillingCycleDay))
                            {
                                difference += 1;
                            }
                            procCharge.ProcCount = difference;
                            remainder            = remainder - difference;
                        }
                        //Stop date was not reached
                        else
                        {
                            procCharge.ProcCount = remainder;
                            remainder            = 0;
                        }
                        procCharge.Calc();
                        _listProcedureCharge.Add(procCharge);
                    }
                    //Found a matching procedurecharge.
                    else
                    {
                        if (_listProcedureCharge[index].HasReachedStopDate)
                        {
                            //Already hit stopdate for this repeat charge so continue on to the next one.
                            continue;
                        }
                        //See if stop date is mindate, if it is then we can add to the count and exit the loop.
                        if (charge.DateStop.Year < 1880)
                        {
                            _listProcedureCharge[index].ProcCount += remainder;
                            remainder = 0;
                            continue;
                        }
                        //Has a stop date, see if we hit it.
                        else
                        {
                            //See if we should use today or the start date.
                            if (DateTimeOD.Today > charge.DateStart)
                            {
                                //See if the count exceeds the difference between today and stop date of this repeat charge.
                                int difference = ((charge.DateStop.Year - DateTimeOD.Today.Year) * 12) + (charge.DateStop.Month - DateTimeOD.Today.Month);
                                if (DateTimeOD.Today.Day < _patCur.BillingCycleDay)
                                {
                                    difference += 1;
                                }
                                int combinedCount = _listProcedureCharge[index].ProcCount + remainder;
                                if (DateTimeOD.Today.AddMonths(combinedCount) >= charge.DateStop)
                                {
                                    //Hit the stop date.
                                    _listProcedureCharge[index].HasReachedStopDate = true;
                                    remainder = combinedCount - difference;
                                    _listProcedureCharge[index].ProcCount = difference;
                                }
                                else
                                {
                                    _listProcedureCharge[index].ProcCount += remainder;
                                    remainder = 0;
                                }
                            }
                            else                              //Start date in future.
                                                              //See if the count exceeds the difference between the start and stop date of this repeat charge.
                            {
                                int difference    = ((charge.DateStop.Year - charge.DateStart.Year) * 12) + (charge.DateStop.Month - charge.DateStart.Month);
                                int combinedCount = _listProcedureCharge[index].ProcCount + remainder;
                                if (combinedCount > difference)
                                {
                                    //Hit the stop date.
                                    _listProcedureCharge[index].HasReachedStopDate = true;
                                    remainder = combinedCount - difference;
                                    _listProcedureCharge[index].ProcCount = difference;
                                }
                                else
                                {
                                    _listProcedureCharge[index].ProcCount += remainder;
                                    remainder = 0;
                                }
                            }
                        }
                    }
                }
            }
        }