· 7 years ago · May 20, 2018, 03:22 AM
1from flask import Flask, request, redirect, url_for, session, g, flash, render_template
2from flask_oauth import OAuth
3import requests
4import urllib
5import json
6from werkzeug.exceptions import BadRequest
7from QBOService import create_customer, get_companyInfo, create_expense
8from utils import excel, context, OAuth2Helper
9import config
10
11# configuration
12SECRET_KEY = 'dev key'
13DEBUG = True
14
15# setup flask
16app = Flask(__name__)
17app.debug = DEBUG
18app.secret_key = SECRET_KEY
19
20if config.AUTH_TYPE == 'OAuth1':
21 oauth = OAuth()
22
23 qbo = oauth.remote_app('qbo',
24 base_url=config.OAUTH1_BASE,
25 request_token_url=config.REQUEST_TOKEN_URL,
26 access_token_url=config.ACCESS_TOKEN_URL,
27 authorize_url=config.AUTHORIZE_URL,
28 consumer_key=config.CONSUMER_KEY,
29 consumer_secret=config.CONSUMER_SECRET
30 )
31
32@app.route('/')
33def index():
34 """Index route"""
35 global customer_list
36 customer_list = excel.load_excel()
37 return render_template(
38 'index.html',
39 customer_dict=customer_list,
40 title="QB Customer Leads",
41 )
42
43@app.route('/new', methods=["GET", "POST"])
44def login():
45 # Ensure the API request is a POST method
46 if request.method == "POST":
47 # Check that the header is posting JSON blob
48 if request.headers['Content-Type'] == 'application/json':
49 # Deconstruct the JSON post to get key, zid and pass
50 # request_data = request.json
51 #requestMe = json.loads(request_data)
52 requestMe = request.json
53 #TODO: Send to meteor appl
54 #requests.post(url=//, data=request_data)
55 if requestMe["params"] == -1:
56 print("Failure")
57 return 'failed'
58
59 requestMe = json.dumps(requestMe).encode('ascii', 'ignore')
60 requests.post(url="http://indietest.au.meteorapp.com/create",data=requestMe)
61 spendtype = requestMe["params"]["spent-type"]
62 amountspent = requestMe["params"]["amt-spent"]["amount"]
63 #spentdetail = requestMe["params"]["spent-detail"]
64
65
66 ##print (request_data)
67 expense = {
68 "AccountRef": {
69 "value": "86",
70 "name": "Visa"
71 },
72 "PaymentType": spendtype,
73 "Line": [
74 {
75 "Amount": amountspent,
76 "DetailType": "AccountBasedExpenseLineDetail",
77 "AccountBasedExpenseLineDetail": {
78 "AccountRef": {
79 "name": "Meals and Entertainment",
80 "value": "13"
81 },
82 "TaxCodeRef": {
83 "value": "2"
84 }
85 }
86 }
87 ]
88 }
89 if config.AUTH_TYPE == 'OAuth1':
90 request_context = context.RequestContextOAuth1(session['realm_id'], session['access_token'],
91 session['access_secret'])
92 else:
93 request_context = context.RequestContext(session['realm_id'], session['access_token'],
94 session['refresh_token'])
95
96 response = create_expense(expense, request_context)
97
98 # If customer added successfully, remove them from html and excel file
99 if (response.status_code == 200):
100 font_color = 'green'
101 flash('Expense successfully added!')
102 return "hi"
103 else:
104 font_color = 'red'
105 flash('Something went wrong: ' + response.text)
106
107 return redirect(url_for('index'))
108
109
110@app.route('/create')
111def expense_me():
112 """Create a new expense"""
113 expense = {
114 "AccountRef": {
115 "value": "86",
116 "name": "Visa"
117 },
118 "PaymentType": "CreditCard",
119 "Line": [
120 {
121 "Amount": 100.00,
122 "DetailType": "AccountBasedExpenseLineDetail",
123 "AccountBasedExpenseLineDetail": {
124 "AccountRef": {
125 "name": "Meals and Entertainment",
126 "value": "13"
127 },
128 "TaxCodeRef": {
129 "value": "2"
130 }
131 }
132 }
133 ]
134 }
135 if config.AUTH_TYPE == 'OAuth1':
136 request_context = context.RequestContextOAuth1(session['realm_id'], session['access_token'], session['access_secret'])
137 else:
138 request_context = context.RequestContext(session['realm_id'], session['access_token'], session['refresh_token'])
139
140 response = create_expense(expense, request_context)
141
142 # If customer added successfully, remove them from html and excel file
143 if (response.status_code == 200):
144 font_color = 'green'
145 flash('Expense successfully added!')
146 return render_template(
147 'index.html',
148 title='QB Customer Leads',
149 text_color=font_color
150 )
151 else:
152 font_color = 'red'
153 flash('Something went wrong: ' + response.text)
154
155 return redirect(url_for('index'))
156
157
158@app.route('/', methods=['POST'])
159def update_table():
160 """Update Excel file after customer is added in QBO"""
161 customer_id = request.form['id']
162
163 if config.AUTH_TYPE == 'OAuth1':
164 request_context = context.RequestContextOAuth1(session['realm_id'], session['access_token'], session['access_secret'])
165 else:
166 request_context = context.RequestContext(session['realm_id'], session['access_token'], session['refresh_token'])
167
168 for customer in customer_list:
169 if customer['Id'] == customer_id:
170 # Create customer object
171 response = create_customer(customer, request_context)
172
173 # If customer added successfully, remove them from html and excel file
174 if (response.status_code == 200):
175 font_color = 'green'
176 new_customer_list = excel.remove_lead(customer_list, customer_id)
177 flash('Customer successfully added!')
178 return render_template(
179 'index.html',
180 customer_dict=new_customer_list,
181 title='QB Customer Leads',
182 text_color=font_color
183 )
184 else:
185 font_color = 'red'
186 flash('Something went wrong: ' + response.text)
187 return redirect(url_for('index'))
188
189@app.route('/company-info')
190def company_info():
191 """Gets CompanyInfo of the connected QBO account"""
192 if config.AUTH_TYPE == 'OAuth1':
193 request_context = context.RequestContextOAuth1(session['realm_id'], session['access_token'], session['access_secret'])
194 else:
195 request_context = context.RequestContext(session['realm_id'], session['access_token'], session['refresh_token'])
196
197 response = get_companyInfo(request_context)
198 if (response.status_code == 200):
199 return render_template(
200 'index.html',
201 customer_dict=customer_list,
202 company_info='Company Name: ' + response.json()['CompanyInfo']['CompanyName'],
203 title='QB Customer Leads',
204 )
205 else:
206 return render_template(
207 'index.html',
208 customer_dict=customer_list,
209 company_info=response.text,
210 title='QB Customer Leads',
211 )
212
213
214@app.route('/auth')
215def auth():
216 """Initiates the Authorization flow after getting the right config value"""
217 if config.AUTH_TYPE == "OAuth1":
218 return qbo.authorize(callback=url_for('oauth_authorized'))
219 else:
220 # OAuth2 initiate authorization flow
221 params = {
222 'scope': 'com.intuit.quickbooks.accounting',
223 'redirect_uri': config.REDIRECT_URI,
224 'response_type': 'code',
225 'client_id': config.CLIENT_ID,
226 'state': csrf_token()
227 }
228 url = OAuth2Helper.get_discovery_doc()['authorization_endpoint'] + '?' + urllib.parse.urlencode(params)
229 return redirect(url)
230
231@app.route('/reset-session')
232def reset_session():
233 """Resets session"""
234 session.pop('qbo_token', None)
235 session['is_authorized'] = False
236 return redirect(request.referrer or url_for('index'))
237
238@app.route('/callback')
239def callback():
240 """Handles callback only for OAuth2"""
241 #session['realmid'] = str(request.args.get('realmId'))
242 state = str(request.args.get('state'))
243 error = str(request.args.get('error'))
244 if error == 'access_denied':
245 return redirect(index)
246 if state is None:
247 return BadRequest()
248 # elif state != csrf_token(): # validate against CSRF attacks
249 # return BadRequest('unauthorized')
250
251 auth_code = str(request.args.get('code'))
252 if auth_code is None:
253 return BadRequest()
254
255 bearer = OAuth2Helper.get_bearer_token(auth_code)
256 realmId = str(request.args.get('realmId'))
257
258 # update session here
259 session['is_authorized'] = True
260 session['realm_id'] = realmId
261 session['access_token'] = bearer['access_token']
262 session['refresh_token'] = bearer['refresh_token']
263
264 return redirect(url_for('index'))
265
266if config.AUTH_TYPE == 'OAuth1':
267 @app.route('/oauth-authorized')
268 @qbo.authorized_handler
269 def oauth_authorized(resp):
270 """Handles callback for OAuth1 only"""
271 realm_id = str(request.args.get('realmId'))
272 next_url = url_for('index')
273 if resp is None:
274 flash(u'You denied the request to sign in.')
275 return redirect(next_url)
276
277 session['is_authorized'] = True
278 session['access_token'] = resp['oauth_token']
279 session['realm_id'] = realm_id
280 session['access_secret'] = resp['oauth_token_secret']
281
282 return redirect(url_for('index'))
283
284if config.AUTH_TYPE == 'OAuth1':
285 @qbo.tokengetter
286 def get_qbo_token(token=None):
287 """Get OAuth1 QBO token"""
288 return session.get('qbo_token')
289
290def csrf_token():
291 token = session.get('csrfToken', None)
292 if token is None:
293 token = OAuth2Helper.secret_key()
294 session['csrfToken'] = token
295 return token
296
297if __name__ == '__main__':
298 app.run()