refactor for slice and rule functionality. general cleanup
This commit is contained in:
parent
9ce52a7cc1
commit
07bb796a5a
79
connection/connections/plaid.py
Executable file
79
connection/connections/plaid.py
Executable file
@ -0,0 +1,79 @@
|
|||||||
|
from .abstract import AbstractConnectionClient
|
||||||
|
import plaid
|
||||||
|
import os
|
||||||
|
import datetime
|
||||||
|
|
||||||
|
|
||||||
|
def format_error(e):
|
||||||
|
return {
|
||||||
|
'error': {
|
||||||
|
'display_message': e.display_message,
|
||||||
|
'error_code': e.code,
|
||||||
|
'error_type': e.type,
|
||||||
|
'error_message': e.message}}
|
||||||
|
|
||||||
|
|
||||||
|
class Connection(AbstractConnectionClient):
|
||||||
|
|
||||||
|
def __init__(self, credentials):
|
||||||
|
self.credentials = credentials
|
||||||
|
|
||||||
|
# Fill in your Plaid API keys -
|
||||||
|
# https://dashboard.plaid.com/account/keys
|
||||||
|
self.PLAID_CLIENT_ID = os.getenv('PLAID_CLIENT_ID')
|
||||||
|
self.PLAID_SECRET = os.getenv('PLAID_SECRET')
|
||||||
|
self.PLAID_PUBLIC_KEY = os.getenv('PLAID_PUBLIC_KEY')
|
||||||
|
# Use 'sandbox' to test with Plaid's Sandbox environment (username: user_good,
|
||||||
|
# password: pass_good)
|
||||||
|
# Use `development` to test with live users and credentials and `production`
|
||||||
|
# to go live
|
||||||
|
self.PLAID_ENV = os.getenv('PLAID_ENV', 'sandbox')
|
||||||
|
# PLAID_PRODUCTS is a comma-separated list of products to use when initializing
|
||||||
|
# Link. Note that this list must contain 'assets' in order for the app to be
|
||||||
|
# able to create and retrieve asset reports.
|
||||||
|
self.PLAID_PRODUCTS = os.getenv('PLAID_PRODUCTS', 'transactions')
|
||||||
|
|
||||||
|
# PLAID_COUNTRY_CODES is a comma-separated list of countries for which users
|
||||||
|
# will be able to select institutions from.
|
||||||
|
self.PLAID_COUNTRY_CODES = os.getenv(
|
||||||
|
'PLAID_COUNTRY_CODES', 'US,CA,GB,FR,ES')
|
||||||
|
self.client = plaid.Client(
|
||||||
|
client_id=self.PLAID_CLIENT_ID,
|
||||||
|
secret=self.PLAID_SECRET,
|
||||||
|
public_key=self.PLAID_PUBLIC_KEY,
|
||||||
|
environment=self.PLAID_ENV,
|
||||||
|
api_version='2019-05-29')
|
||||||
|
|
||||||
|
public_key = self.credentials.get('public_key')
|
||||||
|
if not self.credentials.get('auth_token') and public_key:
|
||||||
|
self.credentials['auth_token'] = self.get_auth_token(public_key)
|
||||||
|
|
||||||
|
def get_auth_token(self, public_token):
|
||||||
|
try:
|
||||||
|
exchange_response = self.client.Item.public_token.exchange(
|
||||||
|
public_token)
|
||||||
|
except plaid.errors.PlaidError as e:
|
||||||
|
return format_error(e)
|
||||||
|
access_token = exchange_response['access_token']
|
||||||
|
return access_token
|
||||||
|
|
||||||
|
def get_transactions(
|
||||||
|
self,
|
||||||
|
start_date=None,
|
||||||
|
end_date=None,
|
||||||
|
auth_token=None):
|
||||||
|
if not auth_token:
|
||||||
|
auth_token = self.credentials.get('auth_token')
|
||||||
|
if not auth_token:
|
||||||
|
raise Exception("Missing Auth Token")
|
||||||
|
if not start_date:
|
||||||
|
start_date = '{:%Y-%m-%d}'.format(
|
||||||
|
datetime.datetime.now() + datetime.timedelta(-30))
|
||||||
|
if not end_date:
|
||||||
|
end_date = '{:%Y-%m-%d}'.format(datetime.datetime.now())
|
||||||
|
try:
|
||||||
|
transactions_resp = self.client.Transactions.get(
|
||||||
|
auth_token, start_date, end_date)
|
||||||
|
except plaid.errors.PlaidError as e:
|
||||||
|
return format_error(e)
|
||||||
|
return transactions_resp
|
||||||
18
connection/migrations/0002_auto_20200106_2335.py
Normal file
18
connection/migrations/0002_auto_20200106_2335.py
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
# Generated by Django 2.2.6 on 2020-01-06 23:35
|
||||||
|
|
||||||
|
from django.db import migrations
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('connection', '0001_initial'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.RenameField(
|
||||||
|
model_name='connection',
|
||||||
|
old_name='connection_path',
|
||||||
|
new_name='type',
|
||||||
|
),
|
||||||
|
]
|
||||||
26
connection/migrations/0003_auto_20200107_0015.py
Normal file
26
connection/migrations/0003_auto_20200107_0015.py
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
# Generated by Django 2.2.6 on 2020-01-07 00:15
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('connection', '0002_auto_20200106_2335'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='ConnectionType',
|
||||||
|
fields=[
|
||||||
|
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
|
('name', models.CharField(max_length=255)),
|
||||||
|
('filename', models.CharField(max_length=255, unique=True)),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
migrations.RenameField(
|
||||||
|
model_name='connection',
|
||||||
|
old_name='type',
|
||||||
|
new_name='type_old',
|
||||||
|
),
|
||||||
|
]
|
||||||
19
connection/migrations/0004_connection_type.py
Normal file
19
connection/migrations/0004_connection_type.py
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
# Generated by Django 2.2.6 on 2020-01-07 00:17
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
import django.db.models.deletion
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('connection', '0003_auto_20200107_0015'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='connection',
|
||||||
|
name='type',
|
||||||
|
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to='connection.ConnectionType'),
|
||||||
|
),
|
||||||
|
]
|
||||||
17
connection/migrations/0005_remove_connection_type_old.py
Normal file
17
connection/migrations/0005_remove_connection_type_old.py
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
# Generated by Django 2.2.6 on 2020-01-07 00:20
|
||||||
|
|
||||||
|
from django.db import migrations
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('connection', '0004_connection_type'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.RemoveField(
|
||||||
|
model_name='connection',
|
||||||
|
name='type_old',
|
||||||
|
),
|
||||||
|
]
|
||||||
12
connection/serializers.py
Executable file
12
connection/serializers.py
Executable file
@ -0,0 +1,12 @@
|
|||||||
|
from .models import Connection
|
||||||
|
from rest_framework import serializers
|
||||||
|
|
||||||
|
|
||||||
|
class ConnectionSerializer(serializers.HyperlinkedModelSerializer):
|
||||||
|
class Meta:
|
||||||
|
model = Connection
|
||||||
|
fields = ['url', 'name', 'type', 'credentials']
|
||||||
|
extra_kwargs = {
|
||||||
|
'type': {'write_only': True},
|
||||||
|
'credentials': {'write_only': True}
|
||||||
|
}
|
||||||
6
connection/urls.py
Executable file
6
connection/urls.py
Executable file
@ -0,0 +1,6 @@
|
|||||||
|
from rest_framework import routers
|
||||||
|
from .views import ConnectionViewSet
|
||||||
|
|
||||||
|
ROUTER = routers.SimpleRouter()
|
||||||
|
ROUTER.register(r'', ConnectionViewSet)
|
||||||
|
urlpatterns = ROUTER.urls
|
||||||
32
qrtr_account/migrations/0005_rule_slice.py
Normal file
32
qrtr_account/migrations/0005_rule_slice.py
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
# Generated by Django 2.2.6 on 2020-02-25 01:43
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
import django.db.models.deletion
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('contenttypes', '0002_remove_content_type_name'),
|
||||||
|
('qrtr_account', '0004_auto_20191126_0231'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='Rule',
|
||||||
|
fields=[
|
||||||
|
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='Slice',
|
||||||
|
fields=[
|
||||||
|
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
|
('name', models.CharField(max_length=250)),
|
||||||
|
('icon', models.CharField(max_length=250)),
|
||||||
|
('budget', models.DecimalField(decimal_places=3, max_digits=100)),
|
||||||
|
('object_id', models.PositiveIntegerField()),
|
||||||
|
('content_type', models.ForeignKey(limit_choices_to=models.Q(models.Q(('app_label', 'qrtr_account'), ('model', 'bank')), models.Q(('app_label', 'qrtr_account'), ('model', 'slice')), _connector='OR'), on_delete=django.db.models.deletion.CASCADE, to='contenttypes.ContentType')),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
]
|
||||||
23
qrtr_account/migrations/0006_auto_20200225_0155.py
Normal file
23
qrtr_account/migrations/0006_auto_20200225_0155.py
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
# Generated by Django 2.2.6 on 2020-02-25 01:55
|
||||||
|
|
||||||
|
from django.db import migrations
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('qrtr_account', '0005_rule_slice'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.RenameField(
|
||||||
|
model_name='slice',
|
||||||
|
old_name='object_id',
|
||||||
|
new_name='parent_id',
|
||||||
|
),
|
||||||
|
migrations.RenameField(
|
||||||
|
model_name='slice',
|
||||||
|
old_name='content_type',
|
||||||
|
new_name='parent_type',
|
||||||
|
),
|
||||||
|
]
|
||||||
56
qrtr_account/migrations/0007_auto_20200225_0239.py
Normal file
56
qrtr_account/migrations/0007_auto_20200225_0239.py
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
# Generated by Django 2.2.6 on 2020-02-25 02:39
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
import django.db.models.deletion
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('qrtr_account', '0006_auto_20200225_0155'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='Schedule',
|
||||||
|
fields=[
|
||||||
|
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
|
('name', models.CharField(max_length=255)),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='rule',
|
||||||
|
name='amount',
|
||||||
|
field=models.DecimalField(decimal_places=3, default=0, max_digits=100),
|
||||||
|
preserve_default=False,
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='rule',
|
||||||
|
name='amount_type',
|
||||||
|
field=models.CharField(choices=[('quantity', 'Quantity'), ('round', 'Round'), ('percent', 'Percent')], default='quantity', max_length=20),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='rule',
|
||||||
|
name='destination',
|
||||||
|
field=models.ForeignKey(default=1, on_delete=django.db.models.deletion.CASCADE, related_name='rule_destination_set', to='qrtr_account.Slice'),
|
||||||
|
preserve_default=False,
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='rule',
|
||||||
|
name='kind',
|
||||||
|
field=models.CharField(choices=[('refill', 'Refill'), ('increase', 'Increase'), ('goal', 'Goal')], default='increase', max_length=255),
|
||||||
|
preserve_default=False,
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='rule',
|
||||||
|
name='source',
|
||||||
|
field=models.ForeignKey(default=1, on_delete=django.db.models.deletion.CASCADE, related_name='rule_source_set', to='qrtr_account.Slice'),
|
||||||
|
preserve_default=False,
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='rule',
|
||||||
|
name='when_to_run',
|
||||||
|
field=models.ForeignKey(default=1, on_delete=django.db.models.deletion.CASCADE, to='qrtr_account.Schedule'),
|
||||||
|
preserve_default=False,
|
||||||
|
),
|
||||||
|
]
|
||||||
Loading…
Reference in New Issue
Block a user