ducky/subscriptions

Paddy 2015-07-18 Parent:b240b6123548 Child:fb2c0e498e37

10:2c8250237566 Go to Latest

ducky/subscriptions/subscription_memstore.go

Update subscription_creator to use the new strategy. When creating subscriptions through the client, detect when the returned error is saying the account already has a subscription, or the subscription already exists in stripe. Add an UpdateSubscription function that will update a subscription through the API. Update our subscription_creator listener to listen for profile creation and login verification messages. This mainly involved fixing the constants (the system, model, and topic) that the listener for profile creation was listening for. It also meant adding a new updateMessageHandler that listens for login verification, tries to create a subscription that has the user ID and email of the login that was verified, and if a subscription already exists, updates it instead to use the email address that was just verified. This will ensure that users get their receipts automatically emailed to them by Stripe.

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