subscriptions.py 3.0 KB

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