Contact
CoCalc Logo Icon
StoreFeaturesDocsShareSupport News AboutSign UpSign In
| Download
Views: 39537
1
###############################################################################
2
#
3
# CoCalc: Collaborative Calculation in the Cloud
4
#
5
# Copyright (C) 2016, Sagemath Inc.
6
#
7
# This program is free software: you can redistribute it and/or modify
8
# it under the terms of the GNU General Public License as published by
9
# the Free Software Foundation, either version 3 of the License, or
10
# (at your option) any later version.
11
#
12
# This program is distributed in the hope that it will be useful,
13
# but WITHOUT ANY WARRANTY; without even the implied warranty of
14
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
# GNU General Public License for more details.
16
#
17
# You should have received a copy of the GNU General Public License
18
# along with this program. If not, see <http://www.gnu.org/licenses/>.
19
#
20
###############################################################################
21
22
{PROJECT_UPGRADES} = require('./schema')
23
24
misc = require('./misc')
25
26
# This is used by the frontend in r_account. It's also used by the backend
27
# to double check the claims of the frontend.
28
# stripe_subscriptions_data = stripe_customer?.subscriptions?.data
29
exports.get_total_upgrades = get_total_upgrades = (stripe_subscriptions_data) ->
30
subs = stripe_subscriptions_data
31
if not subs?
32
return {}
33
total = {}
34
for sub in subs
35
for q in [0...sub.quantity]
36
total = misc.map_sum(total, PROJECT_UPGRADES.membership[sub.plan.id.split('-')[0]].benefits)
37
return total
38
39
#
40
# INPUT:
41
# memberships = {standard:2, premium:1, course:2, ...}
42
# projects = {project_id:{cores:1, network:1, ...}, ...}
43
#
44
# OUTPUT:
45
# {available:{cores:10, network:3, ...}, excess:{project_id:{cores:2, ...}} }
46
#
47
exports.available_upgrades = (stripe_subscriptions_data, projects) ->
48
available = get_total_upgrades(stripe_subscriptions_data) # start with amount available being your quota
49
excess = {} # nothing exceeds quota
50
# sort projects by project_id so that excess will be well defined
51
v = ({project_id: project_id, upgrades: upgrades} for project_id, upgrades of projects)
52
v.sort (a,b) -> misc.cmp(a.project_id, b.project_id)
53
for {project_id, upgrades} in v
54
for prop, curval of upgrades
55
available[prop] ?= 0 # ensure that available is defined for this prop
56
if curval <= available[prop] # if the current value for this project is within what is left, just subtract it off
57
available[prop] -= curval
58
else # otherwise, it goes over, so record by how much in excess, then set available to 0.
59
excess[project_id] ?= {}
60
excess[project_id][prop] = curval - available[prop]
61
available[prop] = 0
62
return available:available, excess:excess
63
64
# INPUT: same as above, but also a single project_id
65
#
66
# OUTPUT: Returns the maximum amount for each upgrade setting that a control
67
# (which starts at 0) for configuring that setting for the project should go up to.
68
#
69
# {cores:2, network:1, disk_quota:2000, memory:1000}
70
#
71
#
72
exports.upgrade_maxes = (stripe_subscriptions_data, projects, project_id) ->
73
{available, excess} = available_upgrades(stripe_subscriptions_data, projects)
74
allocated = projects[project_id]
75
maxes = {}
76
for param, avail of available
77
max = PROJECT_UPGRADES.max_per_project[param] # the maximum allowed for this param for any project
78
alloc = allocated[param] ? 0 # how much has already been allocated to this project
79
maxes[param] = Math.min(alloc + avail, max)
80
return maxes
81
82