ducky/subscriptions

Paddy 2015-09-27 Parent:b240b6123548 Child:fb2c0e498e37

11:0ae1ff0ee306 Go to Latest

ducky/subscriptions/subscription_memstore.go

Add comments, move ChangingSystemProperties to the api package. Add comments to all our exported types and variables in subscription.go, both to make golint happy and because it's good to have comments. Move the subscriptions.ChangingSystemProperties helper to api.changingSystemProperties, because it returns API-specific strings and there's no real reason it has to be in the subscriptions package--everything it needs to work on is exported.

History
paddy@0 1 package subscriptions
paddy@0 2
paddy@0 3 import (
paddy@0 4 "code.secondbit.org/uuid.hg"
paddy@0 5 )
paddy@0 6
paddy@2 7 func stripeSubscriptionInMemstore(stripeSubscription string, m *Memstore) bool {
paddy@0 8 for _, sub := range m.subscriptions {
paddy@2 9 if sub.StripeSubscription == stripeSubscription {
paddy@0 10 return true
paddy@0 11 }
paddy@0 12 }
paddy@0 13 return false
paddy@0 14 }
paddy@0 15
paddy@3 16 func (m *Memstore) CreateSubscription(sub Subscription) error {
paddy@0 17 m.subscriptionLock.Lock()
paddy@0 18 defer m.subscriptionLock.Unlock()
paddy@0 19
paddy@1 20 if _, ok := m.subscriptions[sub.UserID.String()]; ok {
paddy@0 21 return ErrSubscriptionAlreadyExists
paddy@0 22 }
paddy@2 23 if stripeSubscriptionInMemstore(sub.StripeSubscription, m) {
paddy@2 24 return ErrStripeSubscriptionAlreadyExists
paddy@0 25 }
paddy@1 26 m.subscriptions[sub.UserID.String()] = sub
paddy@0 27 return nil
paddy@0 28 }
paddy@0 29
paddy@3 30 func (m *Memstore) UpdateSubscription(id uuid.ID, change SubscriptionChange) error {
paddy@0 31 if change.IsEmpty() {
paddy@0 32 return ErrSubscriptionChangeEmpty
paddy@0 33 }
paddy@0 34
paddy@0 35 m.subscriptionLock.Lock()
paddy@0 36 defer m.subscriptionLock.Unlock()
paddy@0 37
paddy@0 38 s, ok := m.subscriptions[id.String()]
paddy@0 39 if !ok {
paddy@0 40 return ErrSubscriptionNotFound
paddy@0 41 }
paddy@2 42 if change.StripeSubscription != nil {
paddy@2 43 if stripeSubscriptionInMemstore(*change.StripeSubscription, m) {
paddy@2 44 return ErrStripeSubscriptionAlreadyExists
paddy@0 45 }
paddy@0 46 }
paddy@0 47 s.ApplyChange(change)
paddy@0 48 m.subscriptions[id.String()] = s
paddy@0 49 return nil
paddy@0 50 }
paddy@0 51
paddy@3 52 func (m *Memstore) DeleteSubscription(id uuid.ID) error {
paddy@0 53 m.subscriptionLock.Lock()
paddy@0 54 defer m.subscriptionLock.Unlock()
paddy@0 55
paddy@0 56 _, ok := m.subscriptions[id.String()]
paddy@0 57 if !ok {
paddy@0 58 return ErrSubscriptionNotFound
paddy@0 59 }
paddy@0 60 delete(m.subscriptions, id.String())
paddy@0 61 return nil
paddy@0 62 }
paddy@0 63
paddy@3 64 func (m *Memstore) GetSubscriptions(ids []uuid.ID) (map[string]Subscription, error) {
paddy@0 65 if len(ids) < 1 {
paddy@0 66 return map[string]Subscription{}, ErrNoSubscriptionID
paddy@0 67 }
paddy@0 68 m.subscriptionLock.RLock()
paddy@0 69 defer m.subscriptionLock.RUnlock()
paddy@0 70
paddy@0 71 result := map[string]Subscription{}
paddy@0 72
paddy@0 73 for _, id := range ids {
paddy@0 74 s, ok := m.subscriptions[id.String()]
paddy@0 75 if !ok {
paddy@0 76 continue
paddy@0 77 }
paddy@1 78 result[s.UserID.String()] = s
paddy@0 79 }
paddy@0 80 return result, nil
paddy@0 81 }
paddy@0 82
paddy@3 83 func (m *Memstore) GetSubscriptionStats() (SubscriptionStats, error) {
paddy@0 84 m.subscriptionLock.RLock()
paddy@0 85 defer m.subscriptionLock.RUnlock()
paddy@0 86
paddy@2 87 stats := SubscriptionStats{
paddy@2 88 Plans: map[string]int64{},
paddy@2 89 }
paddy@1 90
paddy@0 91 for _, subscription := range m.subscriptions {
paddy@1 92 stats.Number++
paddy@2 93 stats.Plans[subscription.Plan]++
paddy@0 94
paddy@2 95 if subscription.Canceling {
paddy@2 96 stats.Canceling++
paddy@2 97 }
paddy@2 98 if subscription.Status == "past_due" || subscription.Status == "unpaid" {
paddy@2 99 stats.Failing++
paddy@2 100 }
paddy@1 101 }
paddy@1 102 return stats, nil
paddy@0 103 }