/// <summary> /// Given the current date and the aging bucket boundaries (in maximum /// inclusive days from the current date), calculates the days difference /// between the current date and the test date, returning a zero-based number /// of aging bucket that the test date falls into. /// </summary> /// <param name="bucketBoundaries"> /// Upper inclusive boundaries, in days, of the aging buckets. /// The first element of this sequence defines the upper inclusive /// boundary of the current bucket (it is usually zero). /// The total number of buckets would be equal to the number of elements /// in the sequence, plus one. The values in the sequence should /// be strictly non-decreasing. /// </param> /// <returns> /// The number of the aging bucket that the <paramref name="dateToAge"/> /// falls into, in the [0; N] interval, where N is the the number of elements /// in <paramref name="bucketBoundaries"/>. The value of N corresponds /// to the last aging bucket, which encompasses all dates that exceed /// the maximum bucket boundary. /// </returns> public static int AgeByDays( DateTime currentDate, DateTime dateToAge, AgingDirection agingDirection, IEnumerable <int> bucketBoundaries) { if (bucketBoundaries == null) { throw new ArgumentNullException(nameof(bucketBoundaries)); } if (!bucketBoundaries.Any()) { return(0); } if (agingDirection == AgingDirection.Forward) { agingDirection = AgingDirection.Backwards; Utilities.Swap(ref currentDate, ref dateToAge); } int days = currentDate.Subtract(dateToAge).Days; int bucketIndex = bucketBoundaries.FindIndex(boundary => boundary >= days); if (bucketIndex < 0) { bucketIndex = -bucketIndex - 1; } return(bucketIndex); }
public static int AgeByPeriods( DateTime currentDate, DateTime dateToAge, IFinPeriodRepository finPeriodRepository, AgingDirection agingDirection, int numberOfBuckets) => AgeByPeriods( currentDate, dateToAge, finPeriodRepository, agingDirection, numberOfBuckets, FinPeriod.organizationID.MasterValue);
public static IEnumerable <string> GetPeriodAgingBucketDescriptions( IFinPeriodRepository finPeriodRepository, DateTime currentDate, AgingDirection agingDirection, int numberOfBuckets, int calendarOrganizationID, bool usePeriodDescription) { if (finPeriodRepository == null) { throw new ArgumentNullException(nameof(finPeriodRepository)); } if (numberOfBuckets <= 0) { throw new ArgumentOutOfRangeException(nameof(numberOfBuckets)); } short periodStep = (short)(agingDirection == AgingDirection.Backwards ? -1 : 1); FinPeriod currentPeriod = finPeriodRepository.GetByID( finPeriodRepository.GetPeriodIDFromDate(currentDate, calendarOrganizationID), calendarOrganizationID); yield return(usePeriodDescription ? currentPeriod.Descr : FinPeriodUtils.FormatForError(currentPeriod.FinPeriodID)); --numberOfBuckets; while (numberOfBuckets > 1) { currentPeriod = finPeriodRepository.GetByID( finPeriodRepository.GetOffsetPeriodId(currentPeriod.FinPeriodID, periodStep, calendarOrganizationID), calendarOrganizationID); yield return(usePeriodDescription ? currentPeriod.Descr : FinPeriodUtils.FormatForError(currentPeriod.FinPeriodID)); --numberOfBuckets; } if (numberOfBuckets > 0) { yield return(PXMessages.LocalizeFormatNoPrefix( agingDirection == AgingDirection.Backwards ? Messages.BeforeMonth : Messages.AfterMonth, usePeriodDescription ? currentPeriod.Descr : FinPeriodUtils.FormatForError(currentPeriod.FinPeriodID))); } }
public static IEnumerable <string> GetPeriodAgingBucketDescriptions( IFinPeriodRepository finPeriodRepository, DateTime currentDate, AgingDirection agingDirection, int numberOfBuckets) { if (finPeriodRepository == null) { throw new ArgumentNullException(nameof(finPeriodRepository)); } if (numberOfBuckets <= 0) { throw new ArgumentOutOfRangeException(nameof(numberOfBuckets)); } short periodStep = (short)(agingDirection == AgingDirection.Backwards ? -1 : 1); // Must not re-use any existing graphs due to possible query // caching of financial periods, which can impact localization // of their descriptions, see AC-84505. // - PXGraph graph = new PXGraph(); FinPeriod currentPeriod = finPeriodRepository.GetByID( finPeriodRepository.GetPeriodIDFromDate(currentDate, FinPeriod.organizationID.MasterValue), FinPeriod.organizationID.MasterValue); yield return(currentPeriod.Descr); --numberOfBuckets; while (numberOfBuckets > 1) { currentPeriod = finPeriodRepository.GetByID( finPeriodRepository.GetOffsetPeriodId(currentPeriod.FinPeriodID, periodStep, FinPeriod.organizationID.MasterValue), FinPeriod.organizationID.MasterValue); yield return(currentPeriod.Descr); --numberOfBuckets; } if (numberOfBuckets > 0) { yield return(PXMessages.LocalizeFormatNoPrefix( agingDirection == AgingDirection.Backwards ? Messages.BeforeMonth : Messages.AfterMonth, currentPeriod.Descr)); } }
/// <summary> /// Given the current date and the number of period-based aging buckets, /// returns the zero-based number of bucket that the specified test date /// falls into. /// </summary> /// <param name="numberOfBuckets"> /// The total number of period-based buckets, including the "Current" /// and "Over" bucket. For backwards aging, the "Current" bucket encompasses /// dates in the same (or later) financial period as the current date, and /// the "Over" bucket corresponds to dates that are at least (numberOfBuckets - 1) /// periods back in time from the current date. /// </param> public static int AgeByPeriods( DateTime currentDate, DateTime dateToAge, IFinPeriodRepository finPeriodRepository, AgingDirection agingDirection, int numberOfBuckets, int organizationID) { if (finPeriodRepository == null) { throw new ArgumentNullException(nameof(finPeriodRepository)); } if (numberOfBuckets <= 0) { throw new ArgumentOutOfRangeException(nameof(numberOfBuckets)); } if (agingDirection == AgingDirection.Forward) { agingDirection = AgingDirection.Backwards; Utilities.Swap(ref currentDate, ref dateToAge); } if (dateToAge > currentDate) { return(0); } int bucketNumber = finPeriodRepository .PeriodsBetweenInclusive(dateToAge, currentDate, organizationID) .Count(); --bucketNumber; if (bucketNumber < 0) { // No financial periods found between the dates, // cannot proceed with aging. // - throw new PXException(GL.Messages.NoPeriodsDefined); } if (bucketNumber > numberOfBuckets - 1) { // Force into the last ("over") aging bucket. // - bucketNumber = numberOfBuckets - 1; } return(bucketNumber); }
/// <param name="shortFormat"> /// If set to <c>true</c>, then no "Past Due" or "Outstanding" postfix will /// be appended to bucket descriptions, making <paramref name="agingDirection"/> /// parameter irrelevant. /// </param> public static IEnumerable <string> GetDayAgingBucketDescriptions( AgingDirection agingDirection, IEnumerable <int> bucketBoundaries, bool shortFormat) { if (bucketBoundaries == null) { throw new ArgumentNullException(nameof(bucketBoundaries)); } if (!bucketBoundaries.Any()) { yield return(GetDayAgingBucketDescription(null, null, AgingDirection.Backwards, shortFormat)); yield break; } int?currentLowerBoundary = null; int?currentUpperBoundary = null; // Generate descriptions for the "current" and // fully bounded buckets. // - foreach (int boundary in bucketBoundaries) { currentLowerBoundary = currentUpperBoundary; currentUpperBoundary = boundary; yield return(GetDayAgingBucketDescription( currentLowerBoundary, currentUpperBoundary, agingDirection, shortFormat)); } // Generate description for the "over" bucket. // - currentLowerBoundary = currentUpperBoundary; currentUpperBoundary = null; yield return(GetDayAgingBucketDescription( currentLowerBoundary, currentUpperBoundary, agingDirection, shortFormat)); }
public static IEnumerable<string> GetPeriodAgingBucketDescriptions( IFinancialPeriodProvider financialPeriodProvider, DateTime currentDate, AgingDirection agingDirection, int numberOfBuckets) { if (financialPeriodProvider == null) throw new ArgumentNullException(nameof(financialPeriodProvider)); if (numberOfBuckets <= 0) throw new ArgumentOutOfRangeException(nameof(numberOfBuckets)); short periodStep = (short)(agingDirection == AgingDirection.Backwards ? -1 : 1); // Must not re-use any existing graphs due to possible query // caching of financial periods, which can impact localization // of their descriptions, see AC-84505. // - PXGraph graph = new PXGraph(); FinPeriod currentPeriod = financialPeriodProvider.GetFinPeriodByID( graph, financialPeriodProvider.GetPeriodFromDate(graph, currentDate)); yield return currentPeriod.Descr; --numberOfBuckets; while (numberOfBuckets > 1) { currentPeriod = financialPeriodProvider.GetFinPeriodByID( graph, financialPeriodProvider.PeriodPlusPeriod(graph, currentPeriod.FinPeriodID, periodStep)); yield return currentPeriod.Descr; --numberOfBuckets; } if (numberOfBuckets > 0) { yield return PXMessages.LocalizeFormatNoPrefix( agingDirection == AgingDirection.Backwards ? Messages.BeforeMonth : Messages.AfterMonth, currentPeriod.Descr); } }
/// <summary> /// Given the current date and the number of period-based aging buckets, /// returns the zero-based number of bucket that the specified test date /// falls into. /// </summary> /// <param name="numberOfBuckets"> /// The total number of period-based buckets, including the "Current" /// and "Over" bucket. For backwards aging, the "Current" bucket encompasses /// dates in the same (or later) financial period as the current date, and /// the "Over" bucket corresponds to dates that are at least (numberOfBuckets - 1) /// periods back in time from the current date. /// </param> public static int AgeByPeriods( PXGraph graph, DateTime currentDate, DateTime dateToAge, IFinancialPeriodProvider financialPeriodProvider, AgingDirection agingDirection, int numberOfBuckets) { if (graph == null) throw new ArgumentNullException(nameof(graph)); if (financialPeriodProvider == null) throw new ArgumentNullException(nameof(financialPeriodProvider)); if (numberOfBuckets <= 0) throw new ArgumentOutOfRangeException(nameof(numberOfBuckets)); if (agingDirection == AgingDirection.Forward) { agingDirection = AgingDirection.Backwards; Utilities.Swap(ref currentDate, ref dateToAge); } if (dateToAge > currentDate) return 0; int bucketNumber = financialPeriodProvider .PeriodsBetweenInclusive(graph, dateToAge, currentDate) .Count(); --bucketNumber; if (bucketNumber < 0) { // No financial periods found between the dates, // cannot proceed with aging. // - throw new PXException(GL.Messages.NoPeriodsDefined); } if (bucketNumber > numberOfBuckets - 1) { // Force into the last ("over") aging bucket. // - bucketNumber = numberOfBuckets - 1; } return bucketNumber; }
public object GetBucketNumberForAgedReport( DateTime?reportDate, DateTime?dateToAge, int?dayBucketBoundary0, int?dayBucketBoundary1, int?dayBucketBoundary2, int?dayBucketBoundary3, bool?isByFinancialPeriod, bool?isForwardAging, int organizationID) { if (reportDate == null || dayBucketBoundary0 == null || dayBucketBoundary1 == null || dayBucketBoundary2 == null || dayBucketBoundary3 == null) { return(null); } AgingDirection agingDirection = isForwardAging == true ? AgingDirection.Forward : AgingDirection.Backwards; PXGraph graph = new PXGraph(); return(isByFinancialPeriod == true ? AgingEngine.AgeByPeriods( reportDate.Value, dateToAge.Value, graph.GetService <IFinPeriodRepository>(), agingDirection, NUMBER_OF_AGING_BUCKETS, organizationID) : AgingEngine.AgeByDays( reportDate.Value, dateToAge.Value, agingDirection, dayBucketBoundary0 ?? 0, dayBucketBoundary1 ?? 0, dayBucketBoundary2 ?? 0, dayBucketBoundary3 ?? 0)); }
public object GetBucketNumberForAgedReport( DateTime?reportDate, DateTime?dateToAge, int?dayBucketBoundary0, int?dayBucketBoundary1, int?dayBucketBoundary2, int?dayBucketBoundary3, bool?isByFinancialPeriod, bool?isForwardAging) { if (reportDate == null || dayBucketBoundary0 == null || dayBucketBoundary1 == null || dayBucketBoundary2 == null || dayBucketBoundary3 == null) { return(null); } AgingDirection agingDirection = isForwardAging == true ? AgingDirection.Forward : AgingDirection.Backwards; return(isByFinancialPeriod == true ? AgingEngine.AgeByPeriods( new PXGraph(), reportDate.Value, dateToAge.Value, FinancialPeriodProvider.Default, agingDirection, NUMBER_OF_AGING_BUCKETS) : AgingEngine.AgeByDays( reportDate.Value, dateToAge.Value, agingDirection, dayBucketBoundary0 ?? 0, dayBucketBoundary1 ?? 0, dayBucketBoundary2 ?? 0, dayBucketBoundary3 ?? 0)); }
/// <param name="shortFormat"> /// If set to <c>true</c>, then no "Past Due" or "Outstanding" postfix will /// be appended to the bucket description, making <paramref name="agingDirection"/> /// parameter irrelevant. /// </param> public static string GetDayAgingBucketDescription( int?lowerExclusiveBucketBoundary, int?upperInclusiveBucketBoundary, AgingDirection agingDirection, bool shortFormat) { if (lowerExclusiveBucketBoundary == null) { string description = agingDirection == AgingDirection.Backwards ? Messages.Current : Messages.PastDue; return(PXMessages.LocalizeNoPrefix(description)); } else if (lowerExclusiveBucketBoundary != null && upperInclusiveBucketBoundary == null) { string descriptionFormat = shortFormat ? Messages.OverDays : agingDirection == AgingDirection.Backwards ? Messages.OverDaysPastDue : Messages.OverDaysOutstanding; return(PXMessages.LocalizeFormatNoPrefix(descriptionFormat, lowerExclusiveBucketBoundary.Value)); } else if (lowerExclusiveBucketBoundary != null && upperInclusiveBucketBoundary != null) { string descriptionFormat = shortFormat ? Messages.IntervalDays : agingDirection == AgingDirection.Backwards ? Messages.IntervalDaysPastDue : Messages.IntervalDaysOutstanding; return(PXMessages.LocalizeFormatNoPrefix( descriptionFormat, lowerExclusiveBucketBoundary.Value + 1, upperInclusiveBucketBoundary.Value)); } return(null); }
public string GetBucketDescriptionForAgedReport( DateTime?reportDate, int?dayBucketBoundary0, int?dayBucketBoundary1, int?dayBucketBoundary2, int?dayBucketBoundary3, bool?isByFinancialPeriod, bool?isForwardAging, int?bucketIndex) { if (reportDate == null || dayBucketBoundary0 == null || dayBucketBoundary1 == null || dayBucketBoundary2 == null || dayBucketBoundary3 == null || bucketIndex == null) { return(null); } AgingDirection agingDirection = isForwardAging == true ? AgingDirection.Forward : AgingDirection.Backwards; if (isByFinancialPeriod == true) { try { IFinancialPeriodProvider periodProvider = FinancialPeriodProvider.Default; IEnumerable <string> bucketDescriptions = AgingEngine.GetPeriodAgingBucketDescriptions( FinancialPeriodProvider.Default, reportDate.Value, agingDirection, NUMBER_OF_AGING_BUCKETS); return(bucketDescriptions.ElementAtOrDefault(bucketIndex.Value)); } catch (PXFinPeriodException) { throw new PXFinPeriodException( isForwardAging == true ? AR.Messages.UnableToCalculateBucketNamesPeriodsAfterwardsNotDefined : AR.Messages.UnableToCalculateBucketNamesPeriodsPrecedingNotDefined); } } else { IEnumerable <string> bucketDescriptions = AgingEngine.GetDayAgingBucketDescriptions( agingDirection, new int[] { dayBucketBoundary0 ?? 0, dayBucketBoundary1 ?? 0, dayBucketBoundary2 ?? 0, dayBucketBoundary3 ?? 0 }, true); return(bucketDescriptions.ElementAtOrDefault(bucketIndex.Value)); } }
public static int AgeByDays( DateTime currentAge, DateTime dateToAge, AgingDirection agingDirection, params int[] bucketBoundaries) => AgeByDays(currentAge, dateToAge, agingDirection, bucketBoundaries as IEnumerable <int>);
public static IEnumerable <string> GetPeriodAgingBucketDescriptions( IFinPeriodRepository finPeriodRepository, DateTime currentDate, AgingDirection agingDirection, int numberOfBuckets) => GetPeriodAgingBucketDescriptions(finPeriodRepository, currentDate, agingDirection, numberOfBuckets, FinPeriod.organizationID.MasterValue, true);