import logging from pytz import timezone from dateutil.relativedelta import relativedelta LOG = logging.getLogger(__name__) class Subscription(object): title = None purchase_date = None first_issue = None last_issue = None duration = None # servers are eastern time, force this setting eastern = timezone("US/Eastern") def __init__(self, title, start_date, duration): self.title = title self.purchase_date = start_date.replace(tzinfo=self.eastern) self.duration = duration self.first_issue = self._calculate_first_issue(self.purchase_date) self.last_issue = self._calculate_last_issue(self.first_issue, duration) @staticmethod def _calculate_first_issue(start_date): """ Our cutoff is Wed. at 8 a.m., but for simplicity and to make sure everything gets processed, lets cut it off at the end of the day Tues. So the subscription date runs for the time frame ordered from the next Thursday. After Tuesday, it gets filled on the following week. """ tuesday = 1 thursday_offset = 2 week_offset = 7 days_till_tuesday = tuesday - start_date.weekday() LOG.debug( "days till tuesday: {0} = {1} - {2}".format( days_till_tuesday, tuesday, start_date.weekday() ) ) # apply the days till tuesday plus the thursday offset, this may be # negative thursday = start_date + relativedelta(days=days_till_tuesday + thursday_offset) LOG.debug("Thursday calculated to be: {0}".format(thursday)) if thursday < start_date: thursday += relativedelta(days=week_offset) LOG.debug("Thursday adjusted to: {0}".format(thursday)) return thursday @staticmethod def _calculate_last_issue(first_issue, duration): thursday = 3 # apply last_issue = first_issue + relativedelta(months=duration) # re-adjust the day to the closest thursday days_till_thursday = thursday - last_issue.weekday() last_issue += relativedelta(days=days_till_thursday) return last_issue def extend_subscription(self, duration): self.duration += duration self.end_date = self._calculate_last_issue(self.purchase_date, self.duration) def within_subscription(self, title, date): date = date.replace(tzinfo=self.eastern) LOG.debug( "Checking {0} with {1} for between {2} and {3}".format( title, date, self.purchase_date, self.last_issue ) ) return self.title == title and self.purchase_date <= date <= self.last_issue @classmethod def is_within_subscription(cls, subscriptions, order_item): for subscription in subscriptions: if subscription.within_subscription( order_item.product.title, order_item.order.date ): return subscription return None