Merge remote-tracking branch 'remotes/origin/stripe-integration' into add-device

pull/79/head
Chris Veilleux 2019-03-13 19:25:27 -05:00
commit 13095c34b6
25 changed files with 390 additions and 336 deletions

225
api/account/Pipfile.lock generated
View File

@ -1,7 +1,7 @@
{
"_meta": {
"hash": {
"sha256": "daaf58243bb30ef012d7013696ccfce15271d61670ef9bd6cebe9d7ffadefd6e"
"sha256": "3e2ce31477884f9983a6eb644183790f946eafc0b88a068507a8e42512c86d70"
},
"pipfile-spec": 6,
"requires": {
@ -16,100 +16,6 @@
]
},
"default": {
"click": {
"hashes": [
"sha256:2335065e6395b9e67ca716de5f7526736bfa6ceead690adf616d925bdc622b13",
"sha256:5b94b49521f6456670fdb30cd82a4eca9412788a93fa6dd6df72c94d5a8ff2d7"
],
"version": "==7.0"
},
"flask": {
"hashes": [
"sha256:2271c0070dbcb5275fad4a82e29f23ab92682dc45f9dfbc22c02ba9b9322ce48",
"sha256:a080b744b7e345ccfcbc77954861cb05b3c63786e93f2b3875e0913d44b43f05"
],
"index": "pypi",
"version": "==1.0.2"
},
"itsdangerous": {
"hashes": [
"sha256:321b033d07f2a4136d3ec762eac9f16a10ccd60f53c0c91af90217ace7ba1f19",
"sha256:b12271b2047cb23eeb98c8b5622e2e5c5e9abd9784a153e9d8ef9cb4dd09d749"
],
"version": "==1.1.0"
},
"jinja2": {
"hashes": [
"sha256:74c935a1b8bb9a3947c50a54766a969d4846290e1e788ea44c1392163723c3bd",
"sha256:f84be1bb0040caca4cea721fcbbbbd61f9be9464ca236387158b0feea01914a4"
],
"version": "==2.10"
},
"markupsafe": {
"hashes": [
"sha256:048ef924c1623740e70204aa7143ec592504045ae4429b59c30054cb31e3c432",
"sha256:130f844e7f5bdd8e9f3f42e7102ef1d49b2e6fdf0d7526df3f87281a532d8c8b",
"sha256:19f637c2ac5ae9da8bfd98cef74d64b7e1bb8a63038a3505cd182c3fac5eb4d9",
"sha256:1b8a7a87ad1b92bd887568ce54b23565f3fd7018c4180136e1cf412b405a47af",
"sha256:1c25694ca680b6919de53a4bb3bdd0602beafc63ff001fea2f2fc16ec3a11834",
"sha256:1f19ef5d3908110e1e891deefb5586aae1b49a7440db952454b4e281b41620cd",
"sha256:1fa6058938190ebe8290e5cae6c351e14e7bb44505c4a7624555ce57fbbeba0d",
"sha256:31cbb1359e8c25f9f48e156e59e2eaad51cd5242c05ed18a8de6dbe85184e4b7",
"sha256:3e835d8841ae7863f64e40e19477f7eb398674da6a47f09871673742531e6f4b",
"sha256:4e97332c9ce444b0c2c38dd22ddc61c743eb208d916e4265a2a3b575bdccb1d3",
"sha256:525396ee324ee2da82919f2ee9c9e73b012f23e7640131dd1b53a90206a0f09c",
"sha256:52b07fbc32032c21ad4ab060fec137b76eb804c4b9a1c7c7dc562549306afad2",
"sha256:52ccb45e77a1085ec5461cde794e1aa037df79f473cbc69b974e73940655c8d7",
"sha256:5c3fbebd7de20ce93103cb3183b47671f2885307df4a17a0ad56a1dd51273d36",
"sha256:5e5851969aea17660e55f6a3be00037a25b96a9b44d2083651812c99d53b14d1",
"sha256:5edfa27b2d3eefa2210fb2f5d539fbed81722b49f083b2c6566455eb7422fd7e",
"sha256:7d263e5770efddf465a9e31b78362d84d015cc894ca2c131901a4445eaa61ee1",
"sha256:83381342bfc22b3c8c06f2dd93a505413888694302de25add756254beee8449c",
"sha256:857eebb2c1dc60e4219ec8e98dfa19553dae33608237e107db9c6078b1167856",
"sha256:98e439297f78fca3a6169fd330fbe88d78b3bb72f967ad9961bcac0d7fdd1550",
"sha256:bf54103892a83c64db58125b3f2a43df6d2cb2d28889f14c78519394feb41492",
"sha256:d9ac82be533394d341b41d78aca7ed0e0f4ba5a2231602e2f05aa87f25c51672",
"sha256:e982fe07ede9fada6ff6705af70514a52beb1b2c3d25d4e873e82114cf3c5401",
"sha256:edce2ea7f3dfc981c4ddc97add8a61381d9642dc3273737e756517cc03e84dd6",
"sha256:efdc45ef1afc238db84cb4963aa689c0408912a0239b0721cb172b4016eb31d6",
"sha256:f137c02498f8b935892d5c0172560d7ab54bc45039de8805075e19079c639a9c",
"sha256:f82e347a72f955b7017a39708a3667f106e6ad4d10b25f237396a7115d8ed5fd",
"sha256:fb7c206e01ad85ce57feeaaa0bf784b97fa3cad0d4a5737bc5295785f5c613a1"
],
"version": "==1.1.0"
},
"schematics": {
"hashes": [
"sha256:8fcc6182606fd0b24410a1dbb066d9bbddbe8da9c9509f47b743495706239283",
"sha256:a40b20635c0e43d18d3aff76220f6cd95ea4decb3f37765e49529b17d81b0439"
],
"index": "pypi",
"version": "==2.1.0"
},
"uwsgi": {
"hashes": [
"sha256:4972ac538800fb2d421027f49b4a1869b66048839507ccf0aa2fda792d99f583"
],
"index": "pypi",
"version": "==2.0.18"
},
"werkzeug": {
"hashes": [
"sha256:c3fd7a7d41976d9f44db327260e263132466836cef6f91512889ed60ad26557c",
"sha256:d5da73735293558eb1651ee2fddc4d0dedcfa06538b8813a2e20011583c9e49b"
],
"version": "==0.14.1"
}
},
"develop": {
"behave": {
"hashes": [
"sha256:b9662327aa53294c1351b0a9c369093ccec1d21026f050c3bd9b3e5cccf81a86",
"sha256:ebda1a6c9e5bfe95c5f9f0a2794e01c7098b3dde86c10a95d8621c5907ff6f1c"
],
"index": "pypi",
"version": "==1.2.6"
},
"certifi": {
"hashes": [
"sha256:47f9c83ef4c0c621eaef743f133f09fa8a74a9b75f037e8624f83bd1b6626cb7",
@ -133,10 +39,10 @@
},
"deprecated": {
"hashes": [
"sha256:8bfeba6e630abf42b5d111b68a05f7fe3d6de7004391b3cd614947594f87a4ff",
"sha256:b784e0ca85a8c1e694d77e545c10827bd99772392e79d5f5442e761515a1246e"
"sha256:2f293eb0eee34b1fcf3da530fe8fc4b0d71d43ddc2dc78e2ffb444b6c0868557",
"sha256:749f6cdcfbdc3f79258f8154bad43fced95adc632c337675d0385959895894bc"
],
"version": "==1.2.4"
"version": "==1.2.5"
},
"flask": {
"hashes": [
@ -167,58 +73,38 @@
],
"version": "==2.10"
},
"jsonschema": {
"hashes": [
"sha256:000e68abd33c972a5248544925a0cae7d1125f9bf6c58280d37546b946769a08",
"sha256:6ff5f3180870836cae40f06fa10419f557208175f13ad7bc26caa77beb1f6e02"
],
"version": "==2.6.0"
},
"markupsafe": {
"hashes": [
"sha256:048ef924c1623740e70204aa7143ec592504045ae4429b59c30054cb31e3c432",
"sha256:130f844e7f5bdd8e9f3f42e7102ef1d49b2e6fdf0d7526df3f87281a532d8c8b",
"sha256:19f637c2ac5ae9da8bfd98cef74d64b7e1bb8a63038a3505cd182c3fac5eb4d9",
"sha256:1b8a7a87ad1b92bd887568ce54b23565f3fd7018c4180136e1cf412b405a47af",
"sha256:1c25694ca680b6919de53a4bb3bdd0602beafc63ff001fea2f2fc16ec3a11834",
"sha256:1f19ef5d3908110e1e891deefb5586aae1b49a7440db952454b4e281b41620cd",
"sha256:1fa6058938190ebe8290e5cae6c351e14e7bb44505c4a7624555ce57fbbeba0d",
"sha256:31cbb1359e8c25f9f48e156e59e2eaad51cd5242c05ed18a8de6dbe85184e4b7",
"sha256:3e835d8841ae7863f64e40e19477f7eb398674da6a47f09871673742531e6f4b",
"sha256:4e97332c9ce444b0c2c38dd22ddc61c743eb208d916e4265a2a3b575bdccb1d3",
"sha256:525396ee324ee2da82919f2ee9c9e73b012f23e7640131dd1b53a90206a0f09c",
"sha256:52b07fbc32032c21ad4ab060fec137b76eb804c4b9a1c7c7dc562549306afad2",
"sha256:52ccb45e77a1085ec5461cde794e1aa037df79f473cbc69b974e73940655c8d7",
"sha256:5c3fbebd7de20ce93103cb3183b47671f2885307df4a17a0ad56a1dd51273d36",
"sha256:5e5851969aea17660e55f6a3be00037a25b96a9b44d2083651812c99d53b14d1",
"sha256:5edfa27b2d3eefa2210fb2f5d539fbed81722b49f083b2c6566455eb7422fd7e",
"sha256:7d263e5770efddf465a9e31b78362d84d015cc894ca2c131901a4445eaa61ee1",
"sha256:83381342bfc22b3c8c06f2dd93a505413888694302de25add756254beee8449c",
"sha256:857eebb2c1dc60e4219ec8e98dfa19553dae33608237e107db9c6078b1167856",
"sha256:98e439297f78fca3a6169fd330fbe88d78b3bb72f967ad9961bcac0d7fdd1550",
"sha256:bf54103892a83c64db58125b3f2a43df6d2cb2d28889f14c78519394feb41492",
"sha256:d9ac82be533394d341b41d78aca7ed0e0f4ba5a2231602e2f05aa87f25c51672",
"sha256:e982fe07ede9fada6ff6705af70514a52beb1b2c3d25d4e873e82114cf3c5401",
"sha256:edce2ea7f3dfc981c4ddc97add8a61381d9642dc3273737e756517cc03e84dd6",
"sha256:efdc45ef1afc238db84cb4963aa689c0408912a0239b0721cb172b4016eb31d6",
"sha256:f137c02498f8b935892d5c0172560d7ab54bc45039de8805075e19079c639a9c",
"sha256:f82e347a72f955b7017a39708a3667f106e6ad4d10b25f237396a7115d8ed5fd",
"sha256:fb7c206e01ad85ce57feeaaa0bf784b97fa3cad0d4a5737bc5295785f5c613a1"
"sha256:00bc623926325b26bb9605ae9eae8a215691f33cae5df11ca5424f06f2d1f473",
"sha256:09027a7803a62ca78792ad89403b1b7a73a01c8cb65909cd876f7fcebd79b161",
"sha256:09c4b7f37d6c648cb13f9230d847adf22f8171b1ccc4d5682398e77f40309235",
"sha256:1027c282dad077d0bae18be6794e6b6b8c91d58ed8a8d89a89d59693b9131db5",
"sha256:24982cc2533820871eba85ba648cd53d8623687ff11cbb805be4ff7b4c971aff",
"sha256:29872e92839765e546828bb7754a68c418d927cd064fd4708fab9fe9c8bb116b",
"sha256:43a55c2930bbc139570ac2452adf3d70cdbb3cfe5912c71cdce1c2c6bbd9c5d1",
"sha256:46c99d2de99945ec5cb54f23c8cd5689f6d7177305ebff350a58ce5f8de1669e",
"sha256:500d4957e52ddc3351cabf489e79c91c17f6e0899158447047588650b5e69183",
"sha256:535f6fc4d397c1563d08b88e485c3496cf5784e927af890fb3c3aac7f933ec66",
"sha256:62fe6c95e3ec8a7fad637b7f3d372c15ec1caa01ab47926cfdf7a75b40e0eac1",
"sha256:6dd73240d2af64df90aa7c4e7481e23825ea70af4b4922f8ede5b9e35f78a3b1",
"sha256:717ba8fe3ae9cc0006d7c451f0bb265ee07739daf76355d06366154ee68d221e",
"sha256:79855e1c5b8da654cf486b830bd42c06e8780cea587384cf6545b7d9ac013a0b",
"sha256:7c1699dfe0cf8ff607dbdcc1e9b9af1755371f92a68f706051cc8c37d447c905",
"sha256:88e5fcfb52ee7b911e8bb6d6aa2fd21fbecc674eadd44118a9cc3863f938e735",
"sha256:8defac2f2ccd6805ebf65f5eeb132adcf2ab57aa11fdf4c0dd5169a004710e7d",
"sha256:98c7086708b163d425c67c7a91bad6e466bb99d797aa64f965e9d25c12111a5e",
"sha256:9add70b36c5666a2ed02b43b335fe19002ee5235efd4b8a89bfcf9005bebac0d",
"sha256:9bf40443012702a1d2070043cb6291650a0841ece432556f784f004937f0f32c",
"sha256:ade5e387d2ad0d7ebf59146cc00c8044acbd863725f887353a10df825fc8ae21",
"sha256:b00c1de48212e4cc9603895652c5c410df699856a2853135b3967591e4beebc2",
"sha256:b1282f8c00509d99fef04d8ba936b156d419be841854fe901d8ae224c59f0be5",
"sha256:b2051432115498d3562c084a49bba65d97cf251f5a331c64a12ee7e04dacc51b",
"sha256:ba59edeaa2fc6114428f1637ffff42da1e311e29382d81b339c1817d37ec93c6",
"sha256:c8716a48d94b06bb3b2524c2b77e055fb313aeb4ea620c8dd03a105574ba704f",
"sha256:cd5df75523866410809ca100dc9681e301e3c27567cf498077e8551b6d20e42f",
"sha256:e249096428b3ae81b08327a63a485ad0878de3fb939049038579ac0ef61e17e7"
],
"version": "==1.1.0"
},
"parse": {
"hashes": [
"sha256:870dd675c1ee8951db3e29b81ebe44fd131e3eb8c03a79483a58ea574f3145c2"
],
"version": "==1.11.1"
},
"parse-type": {
"hashes": [
"sha256:6e906a66f340252e4c324914a60d417d33a4bea01292ea9bbf68b4fc123be8c9",
"sha256:f596bdc75d3dd93036fbfe3d04127da9f6df0c26c36e01e76da85adef4336b3c"
],
"version": "==0.4.2"
"version": "==1.1.1"
},
"passlib": {
"hashes": [
@ -273,7 +159,6 @@
"sha256:6b672c02fdf7470df9674ab82263841ce8333fb143f32f021f6cb26f0e512420",
"sha256:8ffaa0a53da57e89de14ced7185ac746227a8894dbd5a3c718bf05ddbd1d56cd"
],
"index": "pypi",
"version": "==1.9.0"
},
"pyjwt": {
@ -323,11 +208,12 @@
],
"version": "==1.24.1"
},
"validator-collection": {
"uwsgi": {
"hashes": [
"sha256:e8ddec6d301bd3be40cacb9d4f9f85573bc003e3e17a66ba7267ef46b9a8e3d2"
"sha256:4972ac538800fb2d421027f49b4a1869b66048839507ccf0aa2fda792d99f583"
],
"version": "==1.3.2"
"index": "pypi",
"version": "==2.0.18"
},
"werkzeug": {
"hashes": [
@ -342,5 +228,42 @@
],
"version": "==1.11.1"
}
},
"develop": {
"behave": {
"hashes": [
"sha256:b9662327aa53294c1351b0a9c369093ccec1d21026f050c3bd9b3e5cccf81a86",
"sha256:ebda1a6c9e5bfe95c5f9f0a2794e01c7098b3dde86c10a95d8621c5907ff6f1c"
],
"index": "pypi",
"version": "==1.2.6"
},
"parse": {
"hashes": [
"sha256:870dd675c1ee8951db3e29b81ebe44fd131e3eb8c03a79483a58ea574f3145c2"
],
"version": "==1.11.1"
},
"parse-type": {
"hashes": [
"sha256:6e906a66f340252e4c324914a60d417d33a4bea01292ea9bbf68b4fc123be8c9",
"sha256:f596bdc75d3dd93036fbfe3d04127da9f6df0c26c36e01e76da85adef4336b3c"
],
"version": "==0.4.2"
},
"pyhamcrest": {
"hashes": [
"sha256:6b672c02fdf7470df9674ab82263841ce8333fb143f32f021f6cb26f0e512420",
"sha256:8ffaa0a53da57e89de14ced7185ac746227a8894dbd5a3c718bf05ddbd1d56cd"
],
"version": "==1.9.0"
},
"six": {
"hashes": [
"sha256:3350809f0555b11f552448330d0b52d5f24c91a322ea4a15ef22629740f3761c",
"sha256:d16a0141ec1a18405cd4ce8b4613101da75da0e9a7aec5bdd4fa804d0e0eba73"
],
"version": "==1.12.0"
}
}
}

View File

@ -8,8 +8,9 @@ from .endpoints.account_preferences import AccountPreferencesEndpoint
from .endpoints.device import DeviceEndpoint
from .endpoints.device_count import DeviceCountEndpoint
from .endpoints.geography import GeographyEndpoint
from .endpoints.skills import SkillsEndpoint
from .endpoints.membership import MembershipEndpoint
from .endpoints.skill_settings import SkillSettingsEndpoint
from .endpoints.skills import SkillsEndpoint
from .endpoints.voice_endpoint import VoiceEndpoint
from .endpoints.wake_word_endpoint import WakeWordEndpoint
@ -25,7 +26,7 @@ acct.register_blueprint(selene_api)
acct.add_url_rule(
'/api/account',
view_func=AccountEndpoint.as_view('account_api'),
methods=['GET', 'POST']
methods=['GET', 'POST', 'PATCH']
)
acct.add_url_rule(
'/api/agreement/<string:agreement_type>',
@ -90,3 +91,10 @@ acct.add_url_rule(
view_func=geography_endpoint,
methods=['GET']
)
membership_endpoint = MembershipEndpoint.as_view('membership_endpoint')
acct.add_url_rule(
'/api/memberships',
view_func=membership_endpoint,
methods=['GET']
)

View File

@ -0,0 +1,16 @@
from http import HTTPStatus
from selene.api import SeleneEndpoint
from selene.data.account import MembershipRepository
from selene.util.db import get_db_connection
class MembershipEndpoint(SeleneEndpoint):
def get(self):
with get_db_connection(self.config['DB_CONNECTION_POOL']) as db:
membership_repository = MembershipRepository(db)
membership_types = membership_repository.get_membership_types()
for membership_type in membership_types:
membership_type.rate = float(membership_type.rate)
return membership_types, HTTPStatus.OK

View File

@ -2,7 +2,7 @@ from datetime import date
from behave import given, then, when
from flask import json
from hamcrest import assert_that, equal_to, is_in, none, not_none
from hamcrest import assert_that, equal_to, is_in, none, not_none, starts_with
from selene.data.account import AccountRepository, PRIVACY_POLICY, TERMS_OF_USE
from selene.util.db import get_db_connection
@ -39,7 +39,7 @@ def change_membership_option(context):
context.new_account_request['support'].update(
membership='Monthly Membership',
paymentMethod='Stripe',
paymentAccountId='barstripe'
paymentToken='tok_visa'
)
@ -72,7 +72,7 @@ def check_db_for_account(context, membership_option):
assert_that(account.membership.type, equal_to('Monthly Membership'))
assert_that(
account.membership.payment_account_id,
equal_to('barstripe')
starts_with('cus')
)
elif membership_option == 'without a membership':
assert_that(account.membership, none())

View File

@ -0,0 +1,5 @@
Feature: Test the API call to update a membership
Scenario: user with free account opts into a membership
Given a user with a free account
When a monthly membership is added

View File

@ -12,6 +12,7 @@ flask = "*"
requests = "*"
SpeechRecognition = "*"
uwsgi = "*"
stripe = "*"
[requires]
python_version = "3.7"

View File

@ -1,7 +1,7 @@
{
"_meta": {
"hash": {
"sha256": "5fa825684354d0d9bb2336a9ecdce746401ea0d5c3f1e96b5f508f8a5b237c4c"
"sha256": "334f43f32cee22ca9973853301b232a9e302331dacc5b00f348c93637f89cae3"
},
"pipfile-spec": 6,
"requires": {
@ -114,6 +114,14 @@
"index": "pypi",
"version": "==3.8.1"
},
"stripe": {
"hashes": [
"sha256:170f76f2502888debf02da580138c840497b9359876ca3838f4692f2f02c9110",
"sha256:35441857c8d6969a3f319f0f3cb0ddf853fe36ed451b3b711bc0295241c38444"
],
"index": "pypi",
"version": "==2.21.0"
},
"urllib3": {
"hashes": [
"sha256:61bf29cada3fc2fbefad4fdf059ea4bd1b4a86d2b6d15e1c7c0b582b9752fe39",

View File

@ -1,5 +1,4 @@
import json
from dataclasses import asdict
from http import HTTPStatus
from schematics import Model

View File

@ -43,7 +43,7 @@ def get_device_subscription(context):
access_token = login['accessToken']
headers=dict(Authorization='Bearer {token}'.format(token=access_token))
with get_db_connection(context.client_config['DB_CONNECTION_POOL']) as db:
AccountRepository(db)._add_membership(context.account.id, membership)
AccountRepository(db).add_membership(context.account.id, membership)
context.subscription_response = context.client.get(
'/v1/device/{uuid}/subscription'.format(uuid=device_id),
headers=headers

View File

@ -6,10 +6,10 @@ name = "pypi"
[packages]
flask = "*"
certifi = "*"
selene = {editable = true,path = "./../../shared"}
uwsgi = "*"
[dev-packages]
selene = {editable = true,path = "./../../shared"}
behave = "*"
pyhamcrest = "*"

225
api/sso/Pipfile.lock generated
View File

@ -1,7 +1,7 @@
{
"_meta": {
"hash": {
"sha256": "e27bc9018c42543c8594ffade1899d7d7c9cef2117f4c48462b0971310caeb0f"
"sha256": "8a88efc755cb5bfcda2c6e9db57fb62a506e475386cdcda3da69435427d0a2fe"
},
"pipfile-spec": 6,
"requires": {
@ -16,100 +16,6 @@
]
},
"default": {
"certifi": {
"hashes": [
"sha256:47f9c83ef4c0c621eaef743f133f09fa8a74a9b75f037e8624f83bd1b6626cb7",
"sha256:993f830721089fef441cdfeb4b2c8c9df86f0c63239f06bd025a76a7daddb033"
],
"index": "pypi",
"version": "==2018.11.29"
},
"click": {
"hashes": [
"sha256:2335065e6395b9e67ca716de5f7526736bfa6ceead690adf616d925bdc622b13",
"sha256:5b94b49521f6456670fdb30cd82a4eca9412788a93fa6dd6df72c94d5a8ff2d7"
],
"version": "==7.0"
},
"flask": {
"hashes": [
"sha256:2271c0070dbcb5275fad4a82e29f23ab92682dc45f9dfbc22c02ba9b9322ce48",
"sha256:a080b744b7e345ccfcbc77954861cb05b3c63786e93f2b3875e0913d44b43f05"
],
"index": "pypi",
"version": "==1.0.2"
},
"itsdangerous": {
"hashes": [
"sha256:321b033d07f2a4136d3ec762eac9f16a10ccd60f53c0c91af90217ace7ba1f19",
"sha256:b12271b2047cb23eeb98c8b5622e2e5c5e9abd9784a153e9d8ef9cb4dd09d749"
],
"version": "==1.1.0"
},
"jinja2": {
"hashes": [
"sha256:74c935a1b8bb9a3947c50a54766a969d4846290e1e788ea44c1392163723c3bd",
"sha256:f84be1bb0040caca4cea721fcbbbbd61f9be9464ca236387158b0feea01914a4"
],
"version": "==2.10"
},
"markupsafe": {
"hashes": [
"sha256:048ef924c1623740e70204aa7143ec592504045ae4429b59c30054cb31e3c432",
"sha256:130f844e7f5bdd8e9f3f42e7102ef1d49b2e6fdf0d7526df3f87281a532d8c8b",
"sha256:19f637c2ac5ae9da8bfd98cef74d64b7e1bb8a63038a3505cd182c3fac5eb4d9",
"sha256:1b8a7a87ad1b92bd887568ce54b23565f3fd7018c4180136e1cf412b405a47af",
"sha256:1c25694ca680b6919de53a4bb3bdd0602beafc63ff001fea2f2fc16ec3a11834",
"sha256:1f19ef5d3908110e1e891deefb5586aae1b49a7440db952454b4e281b41620cd",
"sha256:1fa6058938190ebe8290e5cae6c351e14e7bb44505c4a7624555ce57fbbeba0d",
"sha256:31cbb1359e8c25f9f48e156e59e2eaad51cd5242c05ed18a8de6dbe85184e4b7",
"sha256:3e835d8841ae7863f64e40e19477f7eb398674da6a47f09871673742531e6f4b",
"sha256:4e97332c9ce444b0c2c38dd22ddc61c743eb208d916e4265a2a3b575bdccb1d3",
"sha256:525396ee324ee2da82919f2ee9c9e73b012f23e7640131dd1b53a90206a0f09c",
"sha256:52b07fbc32032c21ad4ab060fec137b76eb804c4b9a1c7c7dc562549306afad2",
"sha256:52ccb45e77a1085ec5461cde794e1aa037df79f473cbc69b974e73940655c8d7",
"sha256:5c3fbebd7de20ce93103cb3183b47671f2885307df4a17a0ad56a1dd51273d36",
"sha256:5e5851969aea17660e55f6a3be00037a25b96a9b44d2083651812c99d53b14d1",
"sha256:5edfa27b2d3eefa2210fb2f5d539fbed81722b49f083b2c6566455eb7422fd7e",
"sha256:7d263e5770efddf465a9e31b78362d84d015cc894ca2c131901a4445eaa61ee1",
"sha256:83381342bfc22b3c8c06f2dd93a505413888694302de25add756254beee8449c",
"sha256:857eebb2c1dc60e4219ec8e98dfa19553dae33608237e107db9c6078b1167856",
"sha256:98e439297f78fca3a6169fd330fbe88d78b3bb72f967ad9961bcac0d7fdd1550",
"sha256:bf54103892a83c64db58125b3f2a43df6d2cb2d28889f14c78519394feb41492",
"sha256:d9ac82be533394d341b41d78aca7ed0e0f4ba5a2231602e2f05aa87f25c51672",
"sha256:e982fe07ede9fada6ff6705af70514a52beb1b2c3d25d4e873e82114cf3c5401",
"sha256:edce2ea7f3dfc981c4ddc97add8a61381d9642dc3273737e756517cc03e84dd6",
"sha256:efdc45ef1afc238db84cb4963aa689c0408912a0239b0721cb172b4016eb31d6",
"sha256:f137c02498f8b935892d5c0172560d7ab54bc45039de8805075e19079c639a9c",
"sha256:f82e347a72f955b7017a39708a3667f106e6ad4d10b25f237396a7115d8ed5fd",
"sha256:fb7c206e01ad85ce57feeaaa0bf784b97fa3cad0d4a5737bc5295785f5c613a1"
],
"version": "==1.1.0"
},
"uwsgi": {
"hashes": [
"sha256:4972ac538800fb2d421027f49b4a1869b66048839507ccf0aa2fda792d99f583"
],
"index": "pypi",
"version": "==2.0.18"
},
"werkzeug": {
"hashes": [
"sha256:c3fd7a7d41976d9f44db327260e263132466836cef6f91512889ed60ad26557c",
"sha256:d5da73735293558eb1651ee2fddc4d0dedcfa06538b8813a2e20011583c9e49b"
],
"version": "==0.14.1"
}
},
"develop": {
"behave": {
"hashes": [
"sha256:b9662327aa53294c1351b0a9c369093ccec1d21026f050c3bd9b3e5cccf81a86",
"sha256:ebda1a6c9e5bfe95c5f9f0a2794e01c7098b3dde86c10a95d8621c5907ff6f1c"
],
"index": "pypi",
"version": "==1.2.6"
},
"certifi": {
"hashes": [
"sha256:47f9c83ef4c0c621eaef743f133f09fa8a74a9b75f037e8624f83bd1b6626cb7",
@ -134,10 +40,10 @@
},
"deprecated": {
"hashes": [
"sha256:8bfeba6e630abf42b5d111b68a05f7fe3d6de7004391b3cd614947594f87a4ff",
"sha256:b784e0ca85a8c1e694d77e545c10827bd99772392e79d5f5442e761515a1246e"
"sha256:2f293eb0eee34b1fcf3da530fe8fc4b0d71d43ddc2dc78e2ffb444b6c0868557",
"sha256:749f6cdcfbdc3f79258f8154bad43fced95adc632c337675d0385959895894bc"
],
"version": "==1.2.4"
"version": "==1.2.5"
},
"flask": {
"hashes": [
@ -170,49 +76,36 @@
},
"markupsafe": {
"hashes": [
"sha256:048ef924c1623740e70204aa7143ec592504045ae4429b59c30054cb31e3c432",
"sha256:130f844e7f5bdd8e9f3f42e7102ef1d49b2e6fdf0d7526df3f87281a532d8c8b",
"sha256:19f637c2ac5ae9da8bfd98cef74d64b7e1bb8a63038a3505cd182c3fac5eb4d9",
"sha256:1b8a7a87ad1b92bd887568ce54b23565f3fd7018c4180136e1cf412b405a47af",
"sha256:1c25694ca680b6919de53a4bb3bdd0602beafc63ff001fea2f2fc16ec3a11834",
"sha256:1f19ef5d3908110e1e891deefb5586aae1b49a7440db952454b4e281b41620cd",
"sha256:1fa6058938190ebe8290e5cae6c351e14e7bb44505c4a7624555ce57fbbeba0d",
"sha256:31cbb1359e8c25f9f48e156e59e2eaad51cd5242c05ed18a8de6dbe85184e4b7",
"sha256:3e835d8841ae7863f64e40e19477f7eb398674da6a47f09871673742531e6f4b",
"sha256:4e97332c9ce444b0c2c38dd22ddc61c743eb208d916e4265a2a3b575bdccb1d3",
"sha256:525396ee324ee2da82919f2ee9c9e73b012f23e7640131dd1b53a90206a0f09c",
"sha256:52b07fbc32032c21ad4ab060fec137b76eb804c4b9a1c7c7dc562549306afad2",
"sha256:52ccb45e77a1085ec5461cde794e1aa037df79f473cbc69b974e73940655c8d7",
"sha256:5c3fbebd7de20ce93103cb3183b47671f2885307df4a17a0ad56a1dd51273d36",
"sha256:5e5851969aea17660e55f6a3be00037a25b96a9b44d2083651812c99d53b14d1",
"sha256:5edfa27b2d3eefa2210fb2f5d539fbed81722b49f083b2c6566455eb7422fd7e",
"sha256:7d263e5770efddf465a9e31b78362d84d015cc894ca2c131901a4445eaa61ee1",
"sha256:83381342bfc22b3c8c06f2dd93a505413888694302de25add756254beee8449c",
"sha256:857eebb2c1dc60e4219ec8e98dfa19553dae33608237e107db9c6078b1167856",
"sha256:98e439297f78fca3a6169fd330fbe88d78b3bb72f967ad9961bcac0d7fdd1550",
"sha256:bf54103892a83c64db58125b3f2a43df6d2cb2d28889f14c78519394feb41492",
"sha256:d9ac82be533394d341b41d78aca7ed0e0f4ba5a2231602e2f05aa87f25c51672",
"sha256:e982fe07ede9fada6ff6705af70514a52beb1b2c3d25d4e873e82114cf3c5401",
"sha256:edce2ea7f3dfc981c4ddc97add8a61381d9642dc3273737e756517cc03e84dd6",
"sha256:efdc45ef1afc238db84cb4963aa689c0408912a0239b0721cb172b4016eb31d6",
"sha256:f137c02498f8b935892d5c0172560d7ab54bc45039de8805075e19079c639a9c",
"sha256:f82e347a72f955b7017a39708a3667f106e6ad4d10b25f237396a7115d8ed5fd",
"sha256:fb7c206e01ad85ce57feeaaa0bf784b97fa3cad0d4a5737bc5295785f5c613a1"
"sha256:00bc623926325b26bb9605ae9eae8a215691f33cae5df11ca5424f06f2d1f473",
"sha256:09027a7803a62ca78792ad89403b1b7a73a01c8cb65909cd876f7fcebd79b161",
"sha256:09c4b7f37d6c648cb13f9230d847adf22f8171b1ccc4d5682398e77f40309235",
"sha256:1027c282dad077d0bae18be6794e6b6b8c91d58ed8a8d89a89d59693b9131db5",
"sha256:24982cc2533820871eba85ba648cd53d8623687ff11cbb805be4ff7b4c971aff",
"sha256:29872e92839765e546828bb7754a68c418d927cd064fd4708fab9fe9c8bb116b",
"sha256:43a55c2930bbc139570ac2452adf3d70cdbb3cfe5912c71cdce1c2c6bbd9c5d1",
"sha256:46c99d2de99945ec5cb54f23c8cd5689f6d7177305ebff350a58ce5f8de1669e",
"sha256:500d4957e52ddc3351cabf489e79c91c17f6e0899158447047588650b5e69183",
"sha256:535f6fc4d397c1563d08b88e485c3496cf5784e927af890fb3c3aac7f933ec66",
"sha256:62fe6c95e3ec8a7fad637b7f3d372c15ec1caa01ab47926cfdf7a75b40e0eac1",
"sha256:6dd73240d2af64df90aa7c4e7481e23825ea70af4b4922f8ede5b9e35f78a3b1",
"sha256:717ba8fe3ae9cc0006d7c451f0bb265ee07739daf76355d06366154ee68d221e",
"sha256:79855e1c5b8da654cf486b830bd42c06e8780cea587384cf6545b7d9ac013a0b",
"sha256:7c1699dfe0cf8ff607dbdcc1e9b9af1755371f92a68f706051cc8c37d447c905",
"sha256:88e5fcfb52ee7b911e8bb6d6aa2fd21fbecc674eadd44118a9cc3863f938e735",
"sha256:8defac2f2ccd6805ebf65f5eeb132adcf2ab57aa11fdf4c0dd5169a004710e7d",
"sha256:98c7086708b163d425c67c7a91bad6e466bb99d797aa64f965e9d25c12111a5e",
"sha256:9add70b36c5666a2ed02b43b335fe19002ee5235efd4b8a89bfcf9005bebac0d",
"sha256:9bf40443012702a1d2070043cb6291650a0841ece432556f784f004937f0f32c",
"sha256:ade5e387d2ad0d7ebf59146cc00c8044acbd863725f887353a10df825fc8ae21",
"sha256:b00c1de48212e4cc9603895652c5c410df699856a2853135b3967591e4beebc2",
"sha256:b1282f8c00509d99fef04d8ba936b156d419be841854fe901d8ae224c59f0be5",
"sha256:b2051432115498d3562c084a49bba65d97cf251f5a331c64a12ee7e04dacc51b",
"sha256:ba59edeaa2fc6114428f1637ffff42da1e311e29382d81b339c1817d37ec93c6",
"sha256:c8716a48d94b06bb3b2524c2b77e055fb313aeb4ea620c8dd03a105574ba704f",
"sha256:cd5df75523866410809ca100dc9681e301e3c27567cf498077e8551b6d20e42f",
"sha256:e249096428b3ae81b08327a63a485ad0878de3fb939049038579ac0ef61e17e7"
],
"version": "==1.1.0"
},
"parse": {
"hashes": [
"sha256:870dd675c1ee8951db3e29b81ebe44fd131e3eb8c03a79483a58ea574f3145c2"
],
"version": "==1.11.1"
},
"parse-type": {
"hashes": [
"sha256:6e906a66f340252e4c324914a60d417d33a4bea01292ea9bbf68b4fc123be8c9",
"sha256:f596bdc75d3dd93036fbfe3d04127da9f6df0c26c36e01e76da85adef4336b3c"
],
"version": "==0.4.2"
"version": "==1.1.1"
},
"passlib": {
"hashes": [
@ -267,7 +160,6 @@
"sha256:6b672c02fdf7470df9674ab82263841ce8333fb143f32f021f6cb26f0e512420",
"sha256:8ffaa0a53da57e89de14ced7185ac746227a8894dbd5a3c718bf05ddbd1d56cd"
],
"index": "pypi",
"version": "==1.9.0"
},
"pyjwt": {
@ -277,6 +169,13 @@
],
"version": "==1.7.1"
},
"redis": {
"hashes": [
"sha256:724932360d48e5407e8f82e405ab3650a36ed02c7e460d1e6fddf0f038422b54",
"sha256:9b19425a38fd074eb5795ff2b0d9a55b46a44f91f5347995f27e3ad257a7d775"
],
"version": "==3.2.0"
},
"requests": {
"hashes": [
"sha256:502a824f31acdacb3a35b6690b5fbf0bc41d63a24a45c4004352b0242707598e",
@ -309,6 +208,13 @@
],
"version": "==1.24.1"
},
"uwsgi": {
"hashes": [
"sha256:4972ac538800fb2d421027f49b4a1869b66048839507ccf0aa2fda792d99f583"
],
"index": "pypi",
"version": "==2.0.18"
},
"werkzeug": {
"hashes": [
"sha256:c3fd7a7d41976d9f44db327260e263132466836cef6f91512889ed60ad26557c",
@ -322,5 +228,42 @@
],
"version": "==1.11.1"
}
},
"develop": {
"behave": {
"hashes": [
"sha256:b9662327aa53294c1351b0a9c369093ccec1d21026f050c3bd9b3e5cccf81a86",
"sha256:ebda1a6c9e5bfe95c5f9f0a2794e01c7098b3dde86c10a95d8621c5907ff6f1c"
],
"index": "pypi",
"version": "==1.2.6"
},
"parse": {
"hashes": [
"sha256:870dd675c1ee8951db3e29b81ebe44fd131e3eb8c03a79483a58ea574f3145c2"
],
"version": "==1.11.1"
},
"parse-type": {
"hashes": [
"sha256:6e906a66f340252e4c324914a60d417d33a4bea01292ea9bbf68b4fc123be8c9",
"sha256:f596bdc75d3dd93036fbfe3d04127da9f6df0c26c36e01e76da85adef4336b3c"
],
"version": "==0.4.2"
},
"pyhamcrest": {
"hashes": [
"sha256:6b672c02fdf7470df9674ab82263841ce8333fb143f32f021f6cb26f0e512420",
"sha256:8ffaa0a53da57e89de14ced7185ac746227a8894dbd5a3c718bf05ddbd1d56cd"
],
"version": "==1.9.0"
},
"six": {
"hashes": [
"sha256:3350809f0555b11f552448330d0b52d5f24c91a322ea4a15ef22629740f3761c",
"sha256:d16a0141ec1a18405cd4ce8b4613101da75da0e9a7aec5bdd4fa804d0e0eba73"
],
"version": "==1.12.0"
}
}
}

View File

@ -1,6 +1,6 @@
INSERT INTO
account.membership (type, rate, rate_period)
account.membership (type, rate, rate_period, stripe_plan)
VALUES
('Monthly Membership', 1.99, 'month'),
('Yearly Membership', 19.99, 'year')
('Monthly Membership', 1.99, 'month', 'monthly_premium'),
('Yearly Membership', 19.99, 'year', 'mycroft_ai_premium_annual_1999')
;

View File

@ -1,10 +1,11 @@
CREATE TABLE account.membership (
id uuid PRIMARY KEY
DEFAULT gen_random_uuid(),
type membership_type_enum NOT NULL
type membership_type_enum NOT NULL
UNIQUE,
rate NUMERIC NOT NULL,
rate_period text NOT NULL,
stripe_plan text NOT NULL,
insert_ts TIMESTAMP NOT NULL
DEFAULT CURRENT_TIMESTAMP
);

View File

@ -11,6 +11,7 @@ passlib = "*"
pyhamcrest = "*"
schematics = "*"
redis = "*"
stripe = "*"
[dev-packages]

17
shared/Pipfile.lock generated
View File

@ -1,7 +1,7 @@
{
"_meta": {
"hash": {
"sha256": "c0c1a9ec56002f00c9a50fc67aba1b0463d05323813944a244860fd69f49b75c"
"sha256": "302bee79d7d85ce5050af796f262d7e1000ecf5be0353cdf565273cc1823785a"
},
"pipfile-spec": 6,
"requires": {
@ -32,10 +32,10 @@
},
"deprecated": {
"hashes": [
"sha256:8bfeba6e630abf42b5d111b68a05f7fe3d6de7004391b3cd614947594f87a4ff",
"sha256:b784e0ca85a8c1e694d77e545c10827bd99772392e79d5f5442e761515a1246e"
"sha256:2f293eb0eee34b1fcf3da530fe8fc4b0d71d43ddc2dc78e2ffb444b6c0868557",
"sha256:749f6cdcfbdc3f79258f8154bad43fced95adc632c337675d0385959895894bc"
],
"version": "==1.2.4"
"version": "==1.2.5"
},
"idna": {
"hashes": [
@ -124,6 +124,7 @@
"sha256:502a824f31acdacb3a35b6690b5fbf0bc41d63a24a45c4004352b0242707598e",
"sha256:7bf2a778576d825600030a110f3c0e3e8edc51dfaafe1c146e39a2027784957b"
],
"markers": "python_version >= '3.0'",
"version": "==2.21.0"
},
"schematics": {
@ -141,6 +142,14 @@
],
"version": "==1.12.0"
},
"stripe": {
"hashes": [
"sha256:170f76f2502888debf02da580138c840497b9359876ca3838f4692f2f02c9110",
"sha256:35441857c8d6969a3f319f0f3cb0ddf853fe36ed451b3b711bc0295241c38444"
],
"index": "pypi",
"version": "==2.21.0"
},
"urllib3": {
"hashes": [
"sha256:61bf29cada3fc2fbefad4fdf059ea4bd1b4a86d2b6d15e1c7c0b582b9752fe39",

View File

@ -1,8 +1,10 @@
"""API endpoint to return the a logged-in user's profile"""
import os
from dataclasses import asdict
from datetime import date, datetime, timedelta
from http import HTTPStatus
import stripe
from flask import json, jsonify
from schematics import Model
from schematics.exceptions import ValidationError
@ -14,14 +16,17 @@ from selene.data.account import (
AccountRepository,
AccountMembership,
PRIVACY_POLICY,
TERMS_OF_USE
)
TERMS_OF_USE,
MembershipRepository)
from selene.util.db import get_db_connection
from ..base_endpoint import SeleneEndpoint
MONTHLY_MEMBERSHIP = 'Monthly Membership'
YEARLY_MEMBERSHIP = 'Yearly Membership'
NO_MEMBERSHIP = 'Maybe Later'
STRIPE_PAYMENT = 'Stripe'
stripe.api_key = os.environ['STRIPE_PRIVATE_KEY']
def agreement_accepted(value):
@ -55,16 +60,24 @@ class Support(Model):
required=True,
choices=(MONTHLY_MEMBERSHIP, YEARLY_MEMBERSHIP, NO_MEMBERSHIP)
)
payment_method = StringType()
payment_account_id = StringType()
payment_method = StringType(choices=[STRIPE_PAYMENT])
payment_token = StringType()
def validate_payment_account_id(self, data, value):
if data['membership'] != NO_MEMBERSHIP:
if not data['payment_account_id']:
raise ValidationError(
'Membership requires a payment account ID'
)
return value
class AddMembership(Model):
membership = StringType(
required=True,
choices=(MONTHLY_MEMBERSHIP, YEARLY_MEMBERSHIP, NO_MEMBERSHIP)
)
payment_method = StringType(required=True, choices=[STRIPE_PAYMENT])
payment_token = StringType(required=True)
class UpdateMembership(Model):
membership = StringType(
required=True,
choices=(MONTHLY_MEMBERSHIP, YEARLY_MEMBERSHIP, NO_MEMBERSHIP)
)
class AddAccountRequest(Model):
@ -138,6 +151,11 @@ class AccountEndpoint(SeleneEndpoint):
return jsonify('Account added successfully'), HTTPStatus.OK
def patch(self):
self._authenticate()
self.request_data = json.loads(self.request.data)
self._update_support()
def _validate_request(self):
add_request = AddAccountRequest(dict(
username=self.request_data.get('username'),
@ -168,7 +186,7 @@ class AccountEndpoint(SeleneEndpoint):
open_dataset=support_data.get('openDataset'),
membership=support_data.get('membership'),
payment_method=support_data.get('paymentMethod'),
payment_account_id=support_data.get('paymentAccountId')
payment_token=support_data.get('paymentToken')
))
return support
@ -188,12 +206,15 @@ class AccountEndpoint(SeleneEndpoint):
membership_type = self.request_data['support']['membership']
membership = None
if membership_type != NO_MEMBERSHIP:
payment_account = self.request_data['support']['paymentAccountId']
payment_token = self.request_data['support']['paymentToken']
email = self.request_data['login']['userEnteredEmail']
plan = self._get_plan(membership_type).stripe_plan
payment_account_id, start = self._create_stripe_subscription(payment_token, email, plan)
membership = AccountMembership(
type=membership_type,
start_date=date.today(),
payment_method=self.request_data['support']['paymentMethod'],
payment_account_id=payment_account
payment_account_id=payment_account_id
)
account = Account(
email_address=email_address,
@ -210,3 +231,59 @@ class AccountEndpoint(SeleneEndpoint):
account,
password=password
)
def _create_stripe_subscription(self, customer_id, token, user_email, plan):
if customer_id is None:
customer = stripe.Customer.create(source=token, email=user_email)
customer_id = customer.id
subscription = stripe.Subscription.create(customer=customer_id, items=[{'plan': plan}])
# TODO: store subscription.id
start = subscription.current_period_start
start = date.fromtimestamp(start)
return customer_id, start
def _get_plan(self, plan):
with get_db_connection(self.config['DB_CONNECTION_POOL']) as db:
return MembershipRepository(db).get_membership_by_type(plan)
def _update_support(self):
with get_db_connection(self.config['DB_CONNECTION_POOL']) as db:
membership_repository = MembershipRepository(db)
active_membership = membership_repository.get_active_membership_by_account_id(self.account.id)
if active_membership:
active_membership.end_date = datetime.now()
# TODO: use the subscription id to delete the membership on stripe
membership_repository.finish_membership(active_membership)
add_membership = UpdateMembership(self.request_data.get('support'))
add_membership.validate()
support = self.request_data['support']
membership = support['membership']
stripe_plan = self._get_plan(membership)
stripe_id, start_date = self._create_stripe_subscription(
active_membership.payment_account_id,
None,
self.account.email_address,
stripe_plan
)
else:
add_membership = AddMembership(self.request_data.get('support'))
add_membership.validate()
support = self.request_data['support']
membership = support['membership']
token = support['payment']
stripe_plan = self._get_plan(membership)
stripe_id, start_date = self._create_stripe_subscription(
None,
token,
self.account.email_address,
stripe_plan
)
new_membership = AccountMembership(
start_date=start_date,
payment_method=STRIPE_PAYMENT,
payment_account_id=stripe_id,
type=membership
)
AccountRepository(db).add_membership(self.account.id, new_membership)

View File

@ -1,5 +1,5 @@
from datetime import date
from dataclasses import dataclass
from datetime import date
from typing import List
@ -19,6 +19,8 @@ class AccountMembership(object):
payment_method: str
payment_account_id: str
id: str = None
account_id: str = None
end_date: date = None
@dataclass

View File

@ -7,4 +7,5 @@ class Membership(object):
type: str
rate: Decimal
rate_period: str
stripe_plan: str
id: str = None

View File

@ -35,7 +35,7 @@ class AccountRepository(object):
account_id = self._add_account(account, password)
self._add_agreements(account_id, account.agreements)
if account.membership is not None:
self._add_membership(account_id, account.membership)
self.add_membership(account_id, account.membership)
_log.info('Added account {}'.format(account.email_address))
@ -73,7 +73,7 @@ class AccountRepository(object):
)
self.cursor.insert(request)
def _add_membership(self, acct_id: str, membership: AccountMembership):
def add_membership(self, acct_id: str, membership: AccountMembership):
"""A membership is optional, add it if one was selected"""
request = DatabaseRequest(
sql=get_sql_from_file(

View File

@ -1,3 +1,4 @@
from selene.data.account import AccountMembership
from ..entity.membership import Membership
from ...repository_base import RepositoryBase
@ -6,6 +7,31 @@ class MembershipRepository(RepositoryBase):
def __init__(self, db):
super(MembershipRepository, self).__init__(db, __file__)
def get_membership_types(self):
db_request = self._build_db_request(
sql_file_name='get_membership_types.sql'
)
db_result = self.cursor.select_all(db_request)
return [Membership(**row) for row in db_result]
def get_membership_by_type(self, type: str):
db_request = self._build_db_request(
sql_file_name='get_membership_by_type.sql',
args=dict(type=type)
)
db_result = self.cursor.select_one(db_request)
return Membership(**db_result)
def get_active_membership_by_account_id(self, account_id) -> AccountMembership:
db_request = self._build_db_request(
sql_file_name='get_active_membership_by_account_id.sql',
args=dict(account_id=account_id)
)
db_result = self.cursor.select_one(db_request)
if db_result:
return AccountMembership(**db_result)
def add(self, membership: Membership):
db_request = self._build_db_request(
'add_membership.sql',
@ -21,7 +47,20 @@ class MembershipRepository(RepositoryBase):
def remove(self, membership: Membership):
db_request = self._build_db_request(
'delete_membership.sql',
sql_file_name='delete_membership.sql',
args=dict(membership_id=membership.id)
)
self.cursor.delete(db_request)
def finish_membership(self, membership: AccountMembership):
db_request = self._build_db_request(
sql_file_name='finish_membership.sql',
args=dict(
id=membership.id,
membership_ts_range='[{start},{end}]'.format(
start=membership.start_date,
end=membership.end_date
)
)
)
self.cursor.update(db_request)

View File

@ -0,0 +1,6 @@
UPDATE
account.account_membership
SET
membership_ts_range = %(membership_ts_range)s
WHERE
id = %(id)s

View File

@ -0,0 +1,6 @@
SELECT
*
FROM
account.account_membership
WHERE
account_id = %(account_id)s and membership_ts_range @> '[now,)'

View File

@ -0,0 +1,10 @@
SELECT
id,
type,
rate,
rate_period,
stripe_plan
FROM
account.membership
WHERE
type = %(type)s

View File

@ -0,0 +1,8 @@
SELECT
id,
type,
rate,
rate_period,
stripe_plan
FROM
account.membership

View File

@ -1,9 +0,0 @@
from dataclasses import dataclass
@dataclass
class AccountPreferences(object):
id: str
date_format: str
time_format: str
measurement_system: str