CCrypto VPN public website https://vpn.ccrypto.org/
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

149 lines
3.9 KiB

  1. from datetime import timedelta, date
  2. import pygal
  3. from .models import User
  4. from payments.models import BACKENDS
  5. from payments.models import Payment
  6. PERIOD_VERBOSE_NAME = {
  7. "y": "per month",
  8. "m": "per day",
  9. }
  10. def monthdelta(date, delta):
  11. m = (date.month + delta) % 12
  12. y = date.year + (date.month + delta - 1) // 12
  13. if not m:
  14. m = 12
  15. d = min(
  16. date.day,
  17. [
  18. 31,
  19. 29 if y % 4 == 0 and not y % 400 == 0 else 28,
  20. 31,
  21. 30,
  22. 31,
  23. 30,
  24. 31,
  25. 31,
  26. 30,
  27. 31,
  28. 30,
  29. 31,
  30. ][m - 1],
  31. )
  32. return date.replace(day=d, month=m, year=y)
  33. def last_days(n=30):
  34. now = date.today()
  35. for i in range(n - 1, -1, -1):
  36. yield now - timedelta(days=i)
  37. def last_months(n=12):
  38. now = date.today().replace(day=1)
  39. for i in range(n - 1, -1, -1):
  40. yield monthdelta(now, -i)
  41. def time_filter_future(period, m, df):
  42. def _filter(o):
  43. if period == "m":
  44. return df(o).date() <= m
  45. if period == "y":
  46. return df(o).date().replace(day=1) <= m
  47. return _filter
  48. def time_filter_between(period, m, df):
  49. def _filter(o):
  50. if period == "m":
  51. return (
  52. df(o).year == m.year and df(o).month == m.month and df(o).day == m.day
  53. )
  54. return df(o).date() <= m and df(o).date() > (m - timedelta(days=1))
  55. if period == "y":
  56. return df(o).year == m.year and df(o).month == m.month
  57. return df(o).date().replace(day=1) <= m and df(o).date().replace(day=1) > (
  58. m - timedelta(days=30)
  59. )
  60. return _filter
  61. def users_graph(period):
  62. chart = pygal.Line(fill=True, x_label_rotation=75, show_legend=False)
  63. chart.title = "Users %s" % PERIOD_VERBOSE_NAME[period]
  64. chart.x_labels = []
  65. values = []
  66. gen = last_days(30) if period == "m" else last_months(12)
  67. users = User.objects.all()
  68. for m in gen:
  69. filter_ = time_filter_future(period, m, lambda o: o.date_joined)
  70. users_filtered = filter(filter_, users)
  71. values.append(len(list(users_filtered)))
  72. chart.x_labels.append("%02d/%02d" % (m.month, m.day))
  73. chart.add("Users", values)
  74. return chart.render()
  75. def payments_paid_graph(period):
  76. chart = pygal.StackedBar(x_label_rotation=75, show_legend=True)
  77. chart.x_labels = []
  78. gen = list(last_days(30) if period == "m" else last_months(12))
  79. chart.title = "Payments %s in €" % (PERIOD_VERBOSE_NAME[period])
  80. for m in gen:
  81. chart.x_labels.append("%02d/%02d" % (m.month, m.day))
  82. values = dict()
  83. for backend_id, backend in BACKENDS.items():
  84. values = []
  85. payments = list(
  86. Payment.objects.filter(status="confirmed", backend_id=backend_id)
  87. )
  88. for m in gen:
  89. filter_ = time_filter_between(period, m, lambda o: o.created)
  90. filtered = filter(filter_, payments)
  91. values.append(sum(u.paid_amount for u in filtered) / 100)
  92. chart.add(backend_id, values)
  93. return chart.render()
  94. def payments_success_graph(period):
  95. chart = pygal.StackedBar(x_label_rotation=75, show_legend=True)
  96. chart.x_labels = []
  97. gen = list(last_days(30) if period == "m" else last_months(12))
  98. chart.title = "Successful payments %s" % (PERIOD_VERBOSE_NAME[period])
  99. for m in gen:
  100. chart.x_labels.append("%02d/%02d" % (m.month, m.day))
  101. values = dict()
  102. for backend_id, backend in BACKENDS.items():
  103. values = []
  104. payments = list(
  105. Payment.objects.filter(status="confirmed", backend_id=backend_id)
  106. )
  107. for m in gen:
  108. filter_ = time_filter_between(period, m, lambda o: o.created)
  109. filtered = filter(filter_, payments)
  110. values.append(sum(1 for u in filtered))
  111. chart.add(backend_id, values)
  112. return chart.render()