subscriptions.py 3.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889
  1. import logging
  2. from pytz import timezone
  3. from dateutil.relativedelta import relativedelta
  4. LOG = logging.getLogger(__name__)
  5. class Subscription(object):
  6. title = None
  7. purchase_date = None
  8. first_issue = None
  9. last_issue = None
  10. duration = None
  11. # servers are eastern time, force this setting
  12. eastern = timezone('US/Eastern')
  13. def __init__(self, title, start_date, duration):
  14. self.title = title
  15. self.purchase_date = start_date.replace(tzinfo=self.eastern)
  16. self.duration = duration
  17. self.first_issue = self._calculate_first_issue(self.purchase_date)
  18. self.last_issue = self._calculate_last_issue(self.first_issue,
  19. duration)
  20. @staticmethod
  21. def _calculate_first_issue(start_date):
  22. """
  23. Our cutoff is Wed. at 8 a.m., but for simplicity and to make sure
  24. everything gets processed, lets cut it off at the end of the day Tues.
  25. So the subscription date runs for the time frame ordered from the next
  26. Thursday. After Tuesday, it gets filled on the following week.
  27. """
  28. tuesday = 1
  29. thursday_offset = 2
  30. week_offset = 7
  31. days_till_tuesday = tuesday - start_date.weekday()
  32. LOG.debug("days till tuesday: {0} = {1} - {2}".format(
  33. days_till_tuesday, tuesday, start_date.weekday()))
  34. # apply the days till tuesday plus the thursday offset, this may be
  35. # negative
  36. thursday = start_date + relativedelta(
  37. days=days_till_tuesday + thursday_offset)
  38. LOG.debug("Thursday calculated to be: {0}".format(thursday))
  39. if thursday < start_date:
  40. thursday += relativedelta(days=week_offset)
  41. LOG.debug("Thursday adjusted to: {0}".format(thursday))
  42. return thursday
  43. @staticmethod
  44. def _calculate_last_issue(first_issue, duration):
  45. thursday = 3
  46. # apply
  47. last_issue = first_issue + relativedelta(months=duration)
  48. # re-adjust the day to the closest thursday
  49. days_till_thursday = thursday - last_issue.weekday()
  50. last_issue += relativedelta(days=days_till_thursday)
  51. return last_issue
  52. def extend_subscription(self, duration):
  53. self.duration += duration
  54. self.end_date = self._calculate_last_issue(
  55. self.purchase_date, self.duration)
  56. def within_subscription(self, title, date):
  57. date = date.replace(tzinfo=self.eastern)
  58. LOG.debug("Checking {0} with {1} for between {2} and {3}".format(
  59. title, date, self.purchase_date, self.last_issue))
  60. return (self.title == title and
  61. self.purchase_date <= date <= self.last_issue)
  62. @classmethod
  63. def is_within_subscription(cls, subscriptions, order_item):
  64. for subscription in subscriptions:
  65. if subscription.within_subscription(order_item.product.title,
  66. order_item.order.date):
  67. return subscription
  68. return None