Example #1
0
    def _cycle_end_date(self,
                        reference_date=None,
                        ignore_trial=None,
                        granulate=None):
        ignore_trial_default = False
        granulate_default = False

        ignore_trial = ignore_trial or ignore_trial_default
        granulate = granulate or granulate_default

        if reference_date is None:
            reference_date = timezone.now().date()

        real_cycle_start_date = self._cycle_start_date(reference_date,
                                                       ignore_trial, granulate)

        # we need a current start date in order to compute a current end date
        if not real_cycle_start_date:
            return None

        # during trial and trial cycle is not separated into intervals
        if self.on_trial(reference_date) and not (
                self.separate_cycles_during_trial or granulate):
            return min(self.trial_end, (self.ended_at or datetime.max.date()))

        if self.plan.interval == self.plan.INTERVALS.YEAR:
            relative_delta = {'years': self.plan.interval_count}
        elif self.plan.interval == self.plan.INTERVALS.MONTH:
            relative_delta = {'months': self.plan.interval_count}
        elif self.plan.interval == self.plan.INTERVALS.WEEK:
            relative_delta = {'weeks': self.plan.interval_count}
        else:  # plan.INTERVALS.DAY
            relative_delta = {'days': self.plan.interval_count}

        maximum_cycle_end_date = real_cycle_start_date + relativedelta(
            **relative_delta) - ONE_DAY

        # We know that the cycle end_date is the day before the next cycle start_date,
        # therefore we check if the cycle start_date for our maximum cycle end_date is the same
        # as the initial cycle start_date.
        while True:
            reference_cycle_start_date = self._cycle_start_date(
                maximum_cycle_end_date, ignore_trial, granulate)
            # it means the cycle end_date we got is the right one
            if reference_cycle_start_date == real_cycle_start_date:
                return min(maximum_cycle_end_date,
                           (self.ended_at or datetime.max.date()))
            elif reference_cycle_start_date < real_cycle_start_date:
                # This should never happen in normal conditions, but it may stop infinite looping
                return None

            maximum_cycle_end_date = reference_cycle_start_date - ONE_DAY
Example #2
0
    def _cycle_end_date(self, reference_date=None, ignore_trial=None, granulate=None):
        ignore_trial_default = False
        granulate_default = False

        ignore_trial = ignore_trial or ignore_trial_default
        granulate = granulate or granulate_default

        if reference_date is None:
            reference_date = timezone.now().date()

        real_cycle_start_date = self._cycle_start_date(reference_date, ignore_trial, granulate)

        # we need a current start date in order to compute a current end date
        if not real_cycle_start_date:
            return None

        # during trial and trial cycle is not separated into intervals
        if self.on_trial(reference_date) and not (self.separate_cycles_during_trial or
                                                  granulate):
            return min(self.trial_end, (self.ended_at or datetime.max.date()))

        if self.plan.interval == self.plan.INTERVALS.YEAR:
            relative_delta = {'years': self.plan.interval_count}
        elif self.plan.interval == self.plan.INTERVALS.MONTH:
            relative_delta = {'months': self.plan.interval_count}
        elif self.plan.interval == self.plan.INTERVALS.WEEK:
            relative_delta = {'weeks': self.plan.interval_count}
        else:  # plan.INTERVALS.DAY
            relative_delta = {'days': self.plan.interval_count}

        maximum_cycle_end_date = real_cycle_start_date + relativedelta(**relative_delta) - ONE_DAY

        # We know that the cycle end_date is the day before the next cycle start_date,
        # therefore we check if the cycle start_date for our maximum cycle end_date is the same
        # as the initial cycle start_date.
        while True:
            reference_cycle_start_date = self._cycle_start_date(maximum_cycle_end_date,
                                                                ignore_trial, granulate)
            # it means the cycle end_date we got is the right one
            if reference_cycle_start_date == real_cycle_start_date:
                return min(maximum_cycle_end_date, (self.ended_at or datetime.max.date()))
            elif reference_cycle_start_date < real_cycle_start_date:
                # This should never happen in normal conditions, but it may stop infinite looping
                return None

            maximum_cycle_end_date = reference_cycle_start_date - ONE_DAY
    def test_relative_delta(self):
        # TODO: this

        from silver.utils.dates import relativedelta, ONE_DAY
        from dateutil.rrule import rrule, MONTHLY
        from datetime import datetime, timedelta
        from calendar import monthrange

        # Billing by the last day of each month, with a start date that
        # includes all possible months. (Same basic result)

        # Set up the timescale.
        cycle_start_dates = dt.date(2018, 1, 29)

        # These are each month on the same day.
        # [datetime.datetime(), ...]
        intervals = list(
            rrule(MONTHLY, count=12, bymonthday=-1, dtstart=cycle_start_dates))

        relative_delta = relativedelta(months=1)

        for interval in intervals:
            end_date = interval + relative_delta - ONE_DAY