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