Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Updated to work with Python 3. #1

Open
wants to merge 11 commits into
base: master
Choose a base branch
from
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,8 @@ Installation

<script type="text/javascript" src="https://appcenter.intuit.com/Content/IA/intuit.ipp.anywhere.js"></script>
<script>intuit.ipp.anywhere.setup({
menuProxy: '{{ base_url }}{% url quickbooks:quickbooks.views.blue_dot_menu %}',
grantUrl: '{{ base_url }}{% url quickbooks:quickbooks.views.request_oauth_token %}'
menuProxy: '{{ base_url }}{% url "quickbooks:blue_dot_menu" %}',
grantUrl: '{{ base_url }}{% url "quickbooks:request_oauth_token" %}'
});</script>

8. Add the connect button HTML (perhaps in user preferences):
Expand Down
10 changes: 7 additions & 3 deletions quickbooks/api.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
import urllib
try:
from urllib import quote
except ImportError:
from urllib.parse import quote

from requests_oauthlib import OAuth1Session
from django.conf import settings
from django.contrib.auth.models import User
from django.contrib.auth import get_user_model
from quickbooks.models import QuickbooksToken

APPCENTER_URL_BASE = 'https://appcenter.intuit.com/api/v1/'
Expand Down Expand Up @@ -38,6 +41,7 @@ class DuplicateItemError(ApiError):
class QuickbooksApi(object):
""" This is an interface to the QBD and QBO v3 api."""
def __init__(self, owner_or_token):
User = get_user_model()
if isinstance(owner_or_token, User):
self.token = QuickbooksToken.objects.filter(user=owner_or_token).first()
elif isinstance(owner_or_token, QuickbooksToken):
Expand Down Expand Up @@ -104,7 +108,7 @@ def query(self, query):
It is similar to SQL.
"""
# [todo] - add error handling for v3 query
constructed_url = "{}/company/{}/query?query={}".format(self.url_base, self.realm_id, urllib.quote(query))
constructed_url = "{}/company/{}/query?query={}".format(self.url_base, self.realm_id, quote(query))
return self.session.get(constructed_url).json()

def create(self, object_type, object_body):
Expand Down
103 changes: 27 additions & 76 deletions quickbooks/migrations/0001_initial.py
Original file line number Diff line number Diff line change
@@ -1,76 +1,27 @@
# encoding: utf-8
import datetime
from south.db import db
from south.v2 import SchemaMigration
from django.db import models


class Migration(SchemaMigration):

def forwards(self, orm):

# Adding model 'QuickbooksToken'
db.create_table('quickbooks_quickbookstoken', (
('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
('user', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['auth.User'])),
('access_token', self.gf('django.db.models.fields.CharField')(max_length=64)),
('access_token_secret', self.gf('django.db.models.fields.CharField')(max_length=64)),
('realm_id', self.gf('django.db.models.fields.CharField')(max_length=64)),
('data_source', self.gf('django.db.models.fields.CharField')(max_length=10)),
))
db.send_create_signal('quickbooks', ['QuickbooksToken'])

def backwards(self, orm):

# Deleting model 'QuickbooksToken'
db.delete_table('quickbooks_quickbookstoken')

models = {
'auth.group': {
'Meta': {'object_name': 'Group'},
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
},
'auth.permission': {
'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},
'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
},
'auth.user': {
'Meta': {'object_name': 'User'},
'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2012, 6, 27, 11, 36, 43, 422782)'}),
'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2012, 6, 27, 11, 36, 43, 422631)'}),
'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
},
'contenttypes.contenttype': {
'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
},
'quickbooks.quickbookstoken': {
'Meta': {'object_name': 'QuickbooksToken'},
'access_token': ('django.db.models.fields.CharField', [], {'max_length': '64'}),
'access_token_secret': ('django.db.models.fields.CharField', [], {'max_length': '64'}),
'data_source': ('django.db.models.fields.CharField', [], {'max_length': '10'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'realm_id': ('django.db.models.fields.CharField', [], {'max_length': '64'}),
'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"})
}
}

complete_apps = ['quickbooks']
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
import django_extensions.db.fields.encrypted


class Migration(migrations.Migration):

initial = True

dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
]

operations = [
migrations.CreateModel(
name='QuickbooksToken',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('access_token', django_extensions.db.fields.encrypted.EncryptedCharField(max_length=255)),
('access_token_secret', django_extensions.db.fields.encrypted.EncryptedCharField(max_length=255)),
('realm_id', models.CharField(max_length=64)),
('data_source', models.CharField(max_length=10)),
('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
],
),
]
4 changes: 2 additions & 2 deletions quickbooks/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,10 @@
from django.contrib.auth import get_user_model
from django.conf import settings

User = get_user_model()


class QuickbooksToken(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL)
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
access_token = EncryptedCharField(max_length=255)
access_token_secret = EncryptedCharField(max_length=255)
realm_id = models.CharField(max_length=64)
Expand All @@ -19,6 +18,7 @@ class MissingTokenException(Exception):


def find_quickbooks_token(request_or_user):
User = get_user_model()
if isinstance(request_or_user, User):
user = request_or_user
else:
Expand Down
76 changes: 76 additions & 0 deletions quickbooks/south_migrations/0001_initial.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
# encoding: utf-8
import datetime
from south.db import db
from south.v2 import SchemaMigration
from django.db import models


class Migration(SchemaMigration):

def forwards(self, orm):

# Adding model 'QuickbooksToken'
db.create_table('quickbooks_quickbookstoken', (
('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
('user', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['auth.User'])),
('access_token', self.gf('django.db.models.fields.CharField')(max_length=64)),
('access_token_secret', self.gf('django.db.models.fields.CharField')(max_length=64)),
('realm_id', self.gf('django.db.models.fields.CharField')(max_length=64)),
('data_source', self.gf('django.db.models.fields.CharField')(max_length=10)),
))
db.send_create_signal('quickbooks', ['QuickbooksToken'])

def backwards(self, orm):

# Deleting model 'QuickbooksToken'
db.delete_table('quickbooks_quickbookstoken')

models = {
'auth.group': {
'Meta': {'object_name': 'Group'},
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
},
'auth.permission': {
'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},
'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
},
'auth.user': {
'Meta': {'object_name': 'User'},
'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2012, 6, 27, 11, 36, 43, 422782)'}),
'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2012, 6, 27, 11, 36, 43, 422631)'}),
'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
},
'contenttypes.contenttype': {
'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
},
'quickbooks.quickbookstoken': {
'Meta': {'object_name': 'QuickbooksToken'},
'access_token': ('django.db.models.fields.CharField', [], {'max_length': '64'}),
'access_token_secret': ('django.db.models.fields.CharField', [], {'max_length': '64'}),
'data_source': ('django.db.models.fields.CharField', [], {'max_length': '10'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'realm_id': ('django.db.models.fields.CharField', [], {'max_length': '64'}),
'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"})
}
}

complete_apps = ['quickbooks']
17 changes: 10 additions & 7 deletions quickbooks/urls.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
from django.conf.urls import patterns
from django.conf.urls import url

urlpatterns = patterns('quickbooks.views',
(r'^request_oauth_token/?$', 'request_oauth_token'),
(r'^get_access_token/?$', 'get_access_token'),
(r'^blue_dot_menu/?$', 'blue_dot_menu'),
(r'^disconnect/?$', 'disconnect'),
)
from . import views

app_name = 'quickbooks'

urlpatterns = (
url(r'^request_oauth_token/?$', views.request_oauth_token, name='request_oauth_token'),
url(r'^get_access_token/?$', views.get_access_token, name='get_access_token'),
url(r'^blue_dot_menu/?$', views.blue_dot_menu, name='blue_dot_menu'),
url(r'^disconnect/?$', views.disconnect, name='disconnect'),
)
5 changes: 5 additions & 0 deletions quickbooks/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,11 @@
from .api import QuickbooksApi, AuthenticationFailure
from .signals import qb_connected

try:
unicode
except NameError:
unicode = str

REQUEST_TOKEN_URL = 'https://oauth.intuit.com/oauth/v1/get_request_token'
ACCESS_TOKEN_URL = 'https://oauth.intuit.com/oauth/v1/get_access_token'
AUTHORIZATION_URL = 'https://appcenter.intuit.com/Connect/Begin'
Expand Down