from flask import Flask, request, jsonify, render_template_string
from google.oauth2.service_account import Credentials
from googleapiclient.discovery import build
from googleapiclient.http import MediaIoBaseUpload
import os
import io
import datetime
import json
app = Flask(__name__)
SPREADSHEET_ID = '1rcIJflbC1VIc70F6dnASLFvGQ90TXHhCx0iyxsXR7Ww'
FOLDER_ID = '1brmLNqOMCvRS0TDY6ECHvIBmlRx8pcPz'
# Create service account credentials from environment variable
CREDS_JSON = os.environ.get('GOOGLE_CREDENTIALS')
if CREDS_JSON:
CREDS_INFO = json.loads(CREDS_JSON)
CREDENTIALS = Credentials.from_service_account_info(
CREDS_INFO,
scopes=['https://www.googleapis.com/auth/spreadsheets',
'https://www.googleapis.com/auth/drive.file']
)
def get_sheet_names():
try:
service = build('sheets', 'v4', credentials=CREDENTIALS)
spreadsheet = service.spreadsheets().get(spreadsheetId=SPREADSHEET_ID).execute()
return [sheet['properties']['title'] for sheet in spreadsheet['sheets']]
except Exception as e:
print(f"Error getting sheet names: {str(e)}")
return ['Sheet1']
def ensure_headers(sheet_name):
try:
sheets_service = build('sheets', 'v4', credentials=CREDENTIALS)
headers = [
['項目 Item', '總金額 Total Cost', '發票檔案 Receipt File', '時間 Timestamp', 'IP位址 IP', '付款明細 Payment Details']
]
sheets_service.spreadsheets().values().update(
spreadsheetId=SPREADSHEET_ID,
range=f'{sheet_name}!A1:F1',
valueInputOption='RAW',
body={'values': headers}
).execute()
requests = [{
'repeatCell': {
'range': {
'sheetId': 0,
'startRowIndex': 0,
'endRowIndex': 1
},
'cell': {
'userEnteredFormat': {
'horizontalAlignment': 'CENTER',
'textFormat': {
'bold': True
}
}
},
'fields': 'userEnteredFormat(horizontalAlignment,textFormat)'
}
}]
sheets_service.spreadsheets().batchUpdate(
spreadsheetId=SPREADSHEET_ID,
body={'requests': requests}
).execute()
except Exception as e:
print(f"Error setting headers: {str(e)}")
HTML_TEMPLATE = '''
Purchase Record Form
購買記錄表單 Purchase Record Form
'''
@app.route('/')
def index():
sheet_names = get_sheet_names()
return render_template_string(HTML_TEMPLATE, sheet_names=sheet_names)
@app.route('/submit', methods=['POST'])
def submit():
try:
sheet_name = request.form['sheetName']
product = request.form['product']
file = request.files['receipt']
names = request.form.getlist('names[]')
student_ids = request.form.getlist('studentIds[]')
costs = request.form.getlist('costs[]')
# Calculate total
total_cost = sum(float(cost) for cost in costs)
# Create payment details string
payment_details = []
for name, student_id, cost in zip(names, student_ids, costs):
payment_details.append(f"{name}({student_id}): ${cost}")
payment_details_str = " | ".join(payment_details)
# Initialize Drive service
drive_service = build('drive', 'v3', credentials=CREDENTIALS)
# Check if subfolder exists, if not create it
subfolder_name = sheet_name
subfolder_query = f"name = '{subfolder_name}' and '{FOLDER_ID}' in parents and mimeType = 'application/vnd.google-apps.folder' and trashed = false"
results = drive_service.files().list(q=subfolder_query).execute()
items = results.get('files', [])
if not items:
# Create new subfolder
folder_metadata = {
'name': subfolder_name,
'mimeType': 'application/vnd.google-apps.folder',
'parents': [FOLDER_ID]
}
subfolder = drive_service.files().create(
body=folder_metadata,
fields='id'
).execute()
subfolder_id = subfolder.get('id')
else:
subfolder_id = items[0]['id']
# Upload file to the subfolder
file_metadata = {
'name': f"{datetime.datetime.now().strftime('%Y%m%d_%H%M%S')}_{file.filename}",
'parents': [subfolder_id] # Use subfolder ID instead of main folder ID
}
media = MediaIoBaseUpload(
io.BytesIO(file.read()),
mimetype=file.content_type,
resumable=True
)
uploaded_file = drive_service.files().create(
body=file_metadata,
media_body=media,
fields='id,webViewLink'
).execute()
file_url = uploaded_file.get('webViewLink', '')
# Ensure headers exist
ensure_headers(sheet_name)
# Update Google Sheet
sheets_service = build('sheets', 'v4', credentials=CREDENTIALS)
timestamp = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
ip_address = request.remote_addr
# Create single row entry
values = [[
product,
total_cost,
file_url,
timestamp,
ip_address,
payment_details_str
]]
body = {'values': values}
sheets_service.spreadsheets().values().append(
spreadsheetId=SPREADSHEET_ID,
range=f'{sheet_name}!A:F',
valueInputOption='USER_ENTERED',
body=body
).execute()
return jsonify({'success': True, 'message': 'Data submitted successfully!'})
except Exception as e:
return jsonify({'success': False, 'message': f'Error: {str(e)}'})
if __name__ == '__main__':
app.run(host='0.0.0.0', port=7860)