Merge remote-tracking branch 'remotes/origin/dev' into add-device
# Conflicts: # api/account/account_api/api.py # api/account/tests/features/steps/update_membership.py # shared/selene/api/endpoints/account.py # shared/selene/data/account/repository/sql/get_active_membership_by_account_id.sqlpull/79/head
commit
c851624256
|
@ -64,7 +64,8 @@ def _add_account(context, db):
|
||||||
type='Monthly Membership',
|
type='Monthly Membership',
|
||||||
start_date=date.today(),
|
start_date=date.today(),
|
||||||
payment_method='Stripe',
|
payment_method='Stripe',
|
||||||
payment_account_id='foo'
|
payment_account_id='foo',
|
||||||
|
payment_id='bar'
|
||||||
),
|
),
|
||||||
agreements=[
|
agreements=[
|
||||||
AccountAgreement(type=PRIVACY_POLICY, accept_date=date.today())
|
AccountAgreement(type=PRIVACY_POLICY, accept_date=date.today())
|
||||||
|
|
|
@ -1,10 +1,11 @@
|
||||||
import json
|
import json
|
||||||
|
from datetime import date
|
||||||
|
|
||||||
from behave import given, when, then
|
from behave import given, when, then
|
||||||
from hamcrest import assert_that, equal_to, starts_with, none
|
from hamcrest import assert_that, equal_to, starts_with, none
|
||||||
|
|
||||||
from selene.api.testing import generate_access_token, generate_refresh_token
|
from selene.api.testing import generate_access_token, generate_refresh_token
|
||||||
from selene.data.account import AccountRepository
|
from selene.data.account import AccountRepository, Account, AccountAgreement, PRIVACY_POLICY
|
||||||
from selene.util.db import get_db_connection
|
from selene.util.db import get_db_connection
|
||||||
|
|
||||||
new_account_request = dict(
|
new_account_request = dict(
|
||||||
|
@ -14,11 +15,13 @@ new_account_request = dict(
|
||||||
login=dict(
|
login=dict(
|
||||||
federatedEmail=None,
|
federatedEmail=None,
|
||||||
userEnteredEmail='test@mycroft.ai',
|
userEnteredEmail='test@mycroft.ai',
|
||||||
password='test'
|
password='12345678'
|
||||||
),
|
),
|
||||||
support=dict(
|
support=dict(
|
||||||
openDataset=True,
|
openDataset=True,
|
||||||
membership=None
|
membership='Maybe Later',
|
||||||
|
paymentMethod=None,
|
||||||
|
paymentAccountId=None
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -40,15 +43,20 @@ yearly_membership = {
|
||||||
|
|
||||||
|
|
||||||
@given('a user with a free account')
|
@given('a user with a free account')
|
||||||
def create_account_free_account(context):
|
def create_account(context):
|
||||||
context.client.post(
|
context.account = Account(
|
||||||
'/api/account',
|
email_address='test@mycroft.ai',
|
||||||
data=json.dumps(new_account_request),
|
username='test',
|
||||||
content_type='application_json'
|
refresh_tokens=[],
|
||||||
|
membership=None,
|
||||||
|
agreements=[
|
||||||
|
AccountAgreement(type=PRIVACY_POLICY, accept_date=date.today())
|
||||||
|
]
|
||||||
)
|
)
|
||||||
with get_db_connection(context.client_config['DB_CONNECTION_POOL']) as db:
|
with get_db_connection(context.client_config['DB_CONNECTION_POOL']) as db:
|
||||||
account = AccountRepository(db).get_account_by_email(new_account_request['login']['userEnteredEmail'])
|
acct_repository = AccountRepository(db)
|
||||||
context.account = account
|
account_id = acct_repository.add(context.account, 'foo')
|
||||||
|
context.account.id = account_id
|
||||||
generate_access_token(context)
|
generate_access_token(context)
|
||||||
generate_refresh_token(context)
|
generate_refresh_token(context)
|
||||||
|
|
||||||
|
|
|
@ -8,6 +8,7 @@ CREATE TABLE account.account_membership (
|
||||||
membership_ts_range tsrange NOT NULL,
|
membership_ts_range tsrange NOT NULL,
|
||||||
payment_method payment_method_enum NOT NULL,
|
payment_method payment_method_enum NOT NULL,
|
||||||
payment_account_id text NOT NULL,
|
payment_account_id text NOT NULL,
|
||||||
|
payment_id text NOT NULL,
|
||||||
insert_ts TIMESTAMP NOT NULL
|
insert_ts TIMESTAMP NOT NULL
|
||||||
DEFAULT CURRENT_TIMESTAMP,
|
DEFAULT CURRENT_TIMESTAMP,
|
||||||
EXCLUDE USING gist (account_id WITH =, membership_ts_range with &&),
|
EXCLUDE USING gist (account_id WITH =, membership_ts_range with &&),
|
||||||
|
|
|
@ -207,12 +207,19 @@ class AccountEndpoint(SeleneEndpoint):
|
||||||
payment_token = self.request_data['support']['paymentToken']
|
payment_token = self.request_data['support']['paymentToken']
|
||||||
email = self.request_data['login']['userEnteredEmail']
|
email = self.request_data['login']['userEnteredEmail']
|
||||||
plan = self._get_plan(membership_type).stripe_plan
|
plan = self._get_plan(membership_type).stripe_plan
|
||||||
payment_account_id, start = self._create_stripe_subscription(None, payment_token, email, plan)
|
payment_account_id, start, subscription_id = self._create_stripe_subscription(
|
||||||
|
None,
|
||||||
|
payment_token,
|
||||||
|
email,
|
||||||
|
plan
|
||||||
|
)
|
||||||
|
|
||||||
membership = AccountMembership(
|
membership = AccountMembership(
|
||||||
type=membership_type,
|
type=membership_type,
|
||||||
start_date=date.today(),
|
start_date=date.today(),
|
||||||
payment_method=self.request_data['support']['paymentMethod'],
|
payment_method=self.request_data['support']['paymentMethod'],
|
||||||
payment_account_id=payment_account_id
|
payment_account_id=payment_account_id,
|
||||||
|
payment_id=subscription_id
|
||||||
)
|
)
|
||||||
account = Account(
|
account = Account(
|
||||||
email_address=email_address,
|
email_address=email_address,
|
||||||
|
@ -236,10 +243,9 @@ class AccountEndpoint(SeleneEndpoint):
|
||||||
customer_id = customer.id
|
customer_id = customer.id
|
||||||
subscription = stripe.Subscription.create(customer=customer_id, items=[{'plan': plan}])
|
subscription = stripe.Subscription.create(customer=customer_id, items=[{'plan': plan}])
|
||||||
|
|
||||||
# TODO: store subscription.id
|
|
||||||
start = subscription.current_period_start
|
start = subscription.current_period_start
|
||||||
start = date.fromtimestamp(start)
|
start = date.fromtimestamp(start)
|
||||||
return customer_id, start
|
return customer_id, start, subscription.id
|
||||||
|
|
||||||
def _get_plan(self, plan):
|
def _get_plan(self, plan):
|
||||||
with get_db_connection(self.config['DB_CONNECTION_POOL']) as db:
|
with get_db_connection(self.config['DB_CONNECTION_POOL']) as db:
|
||||||
|
@ -250,38 +256,52 @@ class AccountEndpoint(SeleneEndpoint):
|
||||||
membership_repository = MembershipRepository(db)
|
membership_repository = MembershipRepository(db)
|
||||||
active_membership = membership_repository.get_active_membership_by_account_id(self.account.id)
|
active_membership = membership_repository.get_active_membership_by_account_id(self.account.id)
|
||||||
if active_membership:
|
if active_membership:
|
||||||
active_membership.end_date = datetime.utcnow()
|
self.cancel_membership(active_membership, membership_repository)
|
||||||
# TODO: use the subscription id to delete the membership on stripe
|
membership_type, start_date, stripe_id, subscription_stripe_id = self.update_membership(
|
||||||
membership_repository.finish_membership(active_membership)
|
active_membership)
|
||||||
add_membership = UpdateMembership(self.request_data.get('support'))
|
|
||||||
add_membership.validate()
|
|
||||||
support = self.request_data['support']
|
|
||||||
membership_type = support['membership']
|
|
||||||
membership = self._get_plan(membership_type)
|
|
||||||
stripe_id, start_date = self._create_stripe_subscription(
|
|
||||||
active_membership.payment_account_id,
|
|
||||||
None,
|
|
||||||
self.account.email_address,
|
|
||||||
membership.stripe_plan
|
|
||||||
)
|
|
||||||
else:
|
else:
|
||||||
add_membership = AddMembership(self.request_data.get('support'))
|
membership_type, start_date, stripe_id, subscription_stripe_id = self.create_membership()
|
||||||
add_membership.validate()
|
|
||||||
support = self.request_data['support']
|
|
||||||
membership_type = support['membership']
|
|
||||||
token = support['paymentToken']
|
|
||||||
membership = self._get_plan(membership_type)
|
|
||||||
stripe_id, start_date = self._create_stripe_subscription(
|
|
||||||
None,
|
|
||||||
token,
|
|
||||||
self.account.email_address,
|
|
||||||
membership.stripe_plan
|
|
||||||
)
|
|
||||||
|
|
||||||
new_membership = AccountMembership(
|
new_membership = AccountMembership(
|
||||||
start_date=start_date,
|
start_date=start_date,
|
||||||
payment_method=STRIPE_PAYMENT,
|
payment_method=STRIPE_PAYMENT,
|
||||||
payment_account_id=stripe_id,
|
payment_account_id=stripe_id,
|
||||||
|
payment_id=subscription_stripe_id,
|
||||||
type=membership_type
|
type=membership_type
|
||||||
)
|
)
|
||||||
AccountRepository(db).add_membership(self.account.id, new_membership)
|
AccountRepository(db).add_membership(self.account.id, new_membership)
|
||||||
|
|
||||||
|
def create_membership(self):
|
||||||
|
add_membership = AddMembership(self.request_data.get('support'))
|
||||||
|
add_membership.validate()
|
||||||
|
support = self.request_data['support']
|
||||||
|
membership_type = support['membership']
|
||||||
|
token = support['paymentToken']
|
||||||
|
membership = self._get_plan(membership_type)
|
||||||
|
stripe_id, start_date, subscription_stripe_id = self._create_stripe_subscription(
|
||||||
|
None,
|
||||||
|
token,
|
||||||
|
self.account.email_address,
|
||||||
|
membership.stripe_plan
|
||||||
|
)
|
||||||
|
return membership_type, start_date, stripe_id, subscription_stripe_id
|
||||||
|
|
||||||
|
def update_membership(self, active_membership):
|
||||||
|
add_membership = UpdateMembership(self.request_data.get('support'))
|
||||||
|
add_membership.validate()
|
||||||
|
support = self.request_data['support']
|
||||||
|
membership_type = support['membership']
|
||||||
|
membership = self._get_plan(membership_type)
|
||||||
|
stripe_id, start_date, subscription_stripe_id = self._create_stripe_subscription(
|
||||||
|
active_membership.payment_account_id,
|
||||||
|
None,
|
||||||
|
self.account.email_address,
|
||||||
|
membership.stripe_plan
|
||||||
|
)
|
||||||
|
return membership_type, start_date, stripe_id, subscription_stripe_id
|
||||||
|
|
||||||
|
def cancel_membership(self, active_membership, membership_repository):
|
||||||
|
active_membership.end_date = datetime.utcnow()
|
||||||
|
active_stripe_subscription = stripe.Subscription.retrieve(active_membership.payment_id)
|
||||||
|
active_stripe_subscription.delete()
|
||||||
|
membership_repository.finish_membership(active_membership)
|
||||||
|
|
|
@ -18,6 +18,7 @@ class AccountMembership(object):
|
||||||
start_date: date
|
start_date: date
|
||||||
payment_method: str
|
payment_method: str
|
||||||
payment_account_id: str
|
payment_account_id: str
|
||||||
|
payment_id: str
|
||||||
id: str = None
|
id: str = None
|
||||||
end_date: date = None
|
end_date: date = None
|
||||||
|
|
||||||
|
|
|
@ -83,7 +83,8 @@ class AccountRepository(object):
|
||||||
account_id=acct_id,
|
account_id=acct_id,
|
||||||
membership_type=membership.type,
|
membership_type=membership.type,
|
||||||
payment_method=membership.payment_method,
|
payment_method=membership.payment_method,
|
||||||
payment_account_id=membership.payment_account_id
|
payment_account_id=membership.payment_account_id,
|
||||||
|
payment_id=membership.payment_id
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
self.cursor.insert(request)
|
self.cursor.insert(request)
|
||||||
|
|
|
@ -4,7 +4,8 @@ INSERT INTO
|
||||||
membership_id,
|
membership_id,
|
||||||
membership_ts_range,
|
membership_ts_range,
|
||||||
payment_method,
|
payment_method,
|
||||||
payment_account_id
|
payment_account_id,
|
||||||
|
payment_id
|
||||||
)
|
)
|
||||||
VALUES
|
VALUES
|
||||||
(
|
(
|
||||||
|
@ -19,5 +20,6 @@ VALUES
|
||||||
),
|
),
|
||||||
'[now,]',
|
'[now,]',
|
||||||
%(payment_method)s,
|
%(payment_method)s,
|
||||||
%(payment_account_id)s
|
%(payment_account_id)s,
|
||||||
|
%(payment_id)s
|
||||||
)
|
)
|
||||||
|
|
|
@ -29,7 +29,8 @@ WITH
|
||||||
'type', m.type,
|
'type', m.type,
|
||||||
'start_date', lower(am.membership_ts_range)::DATE,
|
'start_date', lower(am.membership_ts_range)::DATE,
|
||||||
'payment_method', am.payment_method,
|
'payment_method', am.payment_method,
|
||||||
'payment_account_id', am.payment_account_id
|
'payment_account_id', am.payment_account_id,
|
||||||
|
'payment_id', am.payment_id
|
||||||
)
|
)
|
||||||
FROM
|
FROM
|
||||||
account.account_membership am
|
account.account_membership am
|
||||||
|
|
|
@ -3,10 +3,11 @@ SELECT
|
||||||
mem.type,
|
mem.type,
|
||||||
LOWER(acc_mem.membership_ts_range) start_date,
|
LOWER(acc_mem.membership_ts_range) start_date,
|
||||||
acc_mem.payment_method,
|
acc_mem.payment_method,
|
||||||
payment_account_id
|
payment_account_id,
|
||||||
|
payment_id
|
||||||
FROM
|
FROM
|
||||||
account.account_membership acc_mem
|
account.account_membership acc_mem
|
||||||
INNER JOIN
|
INNER JOIN
|
||||||
account.membership mem ON acc_mem.membership_id = mem.id
|
account.membership mem ON acc_mem.membership_id = mem.id
|
||||||
WHERE
|
WHERE
|
||||||
account_id = %(account_id)s AND UPPER(acc_mem.membership_ts_range) IS NULL
|
account_id = %(account_id)s AND UPPER(acc_mem.membership_ts_range) IS NULL
|
||||||
|
|
Loading…
Reference in New Issue