-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmain.py
More file actions
180 lines (144 loc) · 6.4 KB
/
main.py
File metadata and controls
180 lines (144 loc) · 6.4 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
# [START app]
import logging
# [START imports]
from flask import Flask, render_template, request, session, send_from_directory
import requests
import os
import json
from twilio.rest import Client
import firebase_admin
from firebase_admin import credentials
from firebase_admin import db
from authenticate import load_firebase_credentials_into_json
from datetime import datetime
import dateutil.parser
from flask import jsonify
# [END imports]
# [START create_app]
app = Flask(__name__, static_folder='static', static_url_path='')
app.config['SECRET_KEY'] = os.environ.get('FLASK_SECRET_KEY')
# stored in private credentials file that isn't uploaded to repo.
# For information on how heroku stores it, see
# https://softwareengineering.stackexchange.com/questions/163506/how-does-one-handle-sensitive-data-when-using-github-and-heroku
twilio_sid, twilio_auth_token = os.environ.get('TWILIO_SID'), os.environ.get('TWILIO_AUTH_TOKEN')
twilioClient = Client(twilio_sid, twilio_auth_token)
load_firebase_credentials_into_json()
cred = credentials.Certificate('firebase-service-acc-creds.json')
firebase_admin.initialize_app(cred, {'databaseURL': 'https://spoke-ops-tool.firebaseio.com/'})
fb_globals_ref = db.reference('globals').get()
twilio_to_number, twilio_from_number = fb_globals_ref['twilio_to_number'], fb_globals_ref['twilio_from_number']
sh_key = fb_globals_ref['typeform_response_sheet_id']
# [END create_app]
# for documentation on setting up pygsheets:
# https://github.com/nithinmurali/pygsheets
import pygsheets
gc = pygsheets.authorize(outh_nonlocal=True, outh_file="sheets.googleapis.com-python.json", no_cache=True)
sh = gc.open_by_key(sh_key)
# TODO: store these in a database rather than keeping track of all shops via hardcoded list of them.
wksheets = {'WLC': sh.worksheet_by_title('Spoke Delivery (Waterloo)')}
shopNames = {'WLC': 'Waterloo Cycles'}
shopURLS = {'WLC': 'bit.ly/spokeWLC'}
# initialize data
cells = {'WLC': wksheets['WLC'].range('A2:L100', returnas="range")}
# possible values for "shop" values in /complete
shops = ['']
@app.errorhandler(500)
def server_error(e):
# Log the error and stacktrace.
logging.exception('An error occurred during a request.')
return 'An internal error occurred.', 500
# [END app]
@app.route('/')
def index():
return send_from_directory(app.static_folder, 'placeholder_landing_page/index.html')
@app.route('/change-customer', methods=['POST'])
def changeDate():
shopWks = wksheets[session['shop']]
data = request.get_json()
print(data)
# hash key in list of work orders
firebase_key = data['key']
updateObj = {}
for key in data.keys():
if key != "key": # key is the firebase key, copied into the client so that updates can happen to the right obj
updateObj[key] = data[key]
work_orders = db.reference('workOrders').child(firebase_key).update(updateObj)
return json.dumps({'success':True}), 200, {'ContentType':'application/json'}
@app.route('/send-completion', methods=['POST'])
def sendCompletion():
shopWks = wksheets[session['shop']]
data = request.get_json()
# update the completed status for the correct cell. Column name is J for completion
shopWks.update_cell('J' + str(data['key']), True)
smsBody = shopNames[session['shop']] + ' completed a repair for ' + data['name']
twilioClient.api.account.messages.create(
to=twilio_to_number,
from_=twilio_from_number,
body=smsBody)
return json.dumps({'success':True}), 200, {'ContentType':'application/json'}
@app.route('/complete')
def complete():
session['shop'] = request.args.get('shop')
# reload the data when the page is refreshed
cells[session['shop']].fetch()
return render_template('repair_complete.html', shopName=shopNames[session['shop']])
@app.route('/get-orders')
def getOrders():
# fetch orders from firebase
work_orders = db.reference('workOrders').order_by_child('shop_key').equal_to(session['shop']).get()
work_orders_list = []
for key, val in work_orders.items():
val['key'] = key
work_orders_list.append(val)
# fetch records from google sheets, to mark orders that require delivery.
# begin by grabbing the phone numbers
shopCells = cells[session['shop']]
# cell.fetch() was already called to update the DataRange in /complete.
# but now they have to be formatted to send to the frontend.
# grab the last row number from the range string. i.e. A1:J100 --> 100
# subtract header rows.
phones = {}
length = int(shopCells.range.split(':')[1][1:]) - 2
for idx in range(length):
row = shopCells[idx]
if not row[0].value:
continue
curPhoneNum, submitDate = row[3].value, row[6].value
phones[curPhoneNum] = submitDate
for order in work_orders_list:
curPhone = order['customer_phone']
if curPhone in phones:
# heuristic: only consider delivery requests as valid for a particular customer if the customer submitted
# the request within 10 days of the shop's order creation.
if abs((dateutil.parser.parse(order['creation_date']) - dateutil.parser.parse(phones[curPhone])).days) <= 10:
order['delivery_requested'] = True
else:
order['delivery_requested'] = False
return jsonify(work_orders_list)
@app.route('/new-work-order', methods=["POST"])
def newWorkOrder():
orderData = request.get_json()
order = db.reference('workOrders').push()
order.set({
'shop_key': session['shop'],
'customer_name': orderData['customer_name'],
'customer_phone': orderData['customer_phone'],
'repair_summary': orderData['repair_summary'],
'completed': False,
'eta_date': False,
'price': False,
'creation_date': str(datetime.now())
})
messageBody = "Hi %s, thanks for visiting %s! If you'd like your bike delivered with Spoke once the repair is finished, let them know at %s" % (\
orderData['customer_name'].split(" ")[0], shopNames[session['shop']], shopURLS[session['shop']])
twilioClient.api.account.messages.create(
to=orderData['customer_phone'],
from_=twilio_from_number,
body=messageBody)
return 'ok'
@app.route('/wakemydyno.txt')
def wakemydyno():
return send_from_directory(app.static_folder, request.path[1:])
if __name__ == "__main__":
port = int(os.environ.get("PORT", 5000))
app.run(host='0.0.0.0', port=port)